[SOLVED] Very simple method to use the QSPI N25Q128A to store the application bitmaps
At this time I am developing a graphic touch screen application on STN32F746-DISCO.
This is a very simple method to store the bitmaps on QSPI N25Q128A in order to save flash space.
I have used the lcd-image-converter.exe to convert the bitmap files to a bitmap structure to pass to BSP_LCD_DrawBitmap().
Here the settings used for cd-image-converter.exe.



Here the logo.h file generated
#ifndef logo_H_
#define logo_H_
#include <stdint.h>
// struct packing, pragma for GCC !!!
#pragma pack(push, 1)
typedef struct logo_tagBITMAPFILEHEADER {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
} logo_BITMAPFILEHEADER; // size is 14 bytes
typedef struct logo_tagBITMAPINFOHEADER {
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} logo_BITMAPINFOHEADER; // size is 40 bytes
typedef struct logo_tag_Struct {
// offset 0, size 14
logo_BITMAPFILEHEADER fileHeader;
// offset 14, size 40
logo_BITMAPINFOHEADER infoHeader;
// offset 54, size 51600 words
uint16_t data[51600];
} logo_Struct;
const logo_Struct logo = {
{
0x4d42u,
sizeof(logo_BITMAPINFOHEADER) + sizeof(logo_BITMAPFILEHEADER) + (51600 * 2),
0x0000u,
0x0000u,
sizeof(logo_BITMAPINFOHEADER) + sizeof(logo_BITMAPFILEHEADER)
},
{
sizeof(logo_BITMAPINFOHEADER),
400,
129,
1u,
16,
0x00000003u,
(51600 * 2),
0x00000000ul,
0x00000000ul,
0x00000000ul,
0x00000000ul
},
{
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, .....
}
};
// struct packing, pragma for GCC !!!
#pragma pack (pop)
#endif /* settings1_H_ */Here the logo.h file modified by hand to use the QSPI
#include <stdint.h>
// struct packing, pragma for GCC !!!
#pragma pack(push, 1)
typedef struct logo_tagBITMAPFILEHEADER {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
} logo_BITMAPFILEHEADER; // size is 14 bytes
typedef struct logo_tagBITMAPINFOHEADER {
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} logo_BITMAPINFOHEADER; // size is 40 bytes
typedef struct logo_tag_Struct {
// offset 0, size 14
logo_BITMAPFILEHEADER fileHeader;
// offset 14, size 40
logo_BITMAPINFOHEADER infoHeader;
// offset 54, size 51600 words
uint16_t data[51600];
} logo_Struct;
#ifndef IMG_NO_DATA
#if defined ( __ICCARM__ )
#pragma location = ".textqspi"
#else
__attribute__((section(".textqspi")))
#endif
const logo_Struct logo = {
{
0x4d42u,
sizeof(logo_BITMAPINFOHEADER) + sizeof(logo_BITMAPFILEHEADER) + (51600 * 2),
0x0000u,
0x0000u,
sizeof(logo_BITMAPINFOHEADER) + sizeof(logo_BITMAPFILEHEADER)
},
{
sizeof(logo_BITMAPINFOHEADER),
400,
129,
1u,
16,
0x00000003u,
(51600 * 2),
0x00000000ul,
0x00000000ul,
0x00000000ul,
0x00000000ul
},
{
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, .....
}
};
#else
extern const logo_Struct logo;
#endif
// struct packing, pragma for GCC !!!
#pragma pack (pop)
create in the project a main_image.c file with only these lines
#include "logo.h"
void dummy_init (void);
void dummy_init (void)
{
}in your main.c use these lines
#define IMG_NO_DATA
#include "logo.h"
QSPI_HandleTypeDef hqspi; hqspi.Instance = QUADSPI; hqspi.Init.ClockPrescaler = 255; hqspi.Init.FifoThreshold = 1; hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; hqspi.Init.FlashSize = 1; hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; hqspi.Init.FlashID = QSPI_FLASH_ID_1; hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; if (HAL_QSPI_Init(&hqspi) != HAL_OK) { Error_Handler(); } int status = BSP_QSPI_Init(); if (status == QSPI_NOT_SUPPORTED) { BSP_LCD_DisplayStringAt(20, 10, (uint8_t*)"QSPI Initialization : FAILED.", LEFT_MODE); } else if (status == QSPI_ERROR) { BSP_LCD_DisplayStringAt(20, 10, (uint8_t*)"QSPI Initialization : FAILED.", LEFT_MODE); } else { BSP_LCD_DisplayStringAt(20, 10, (uint8_t*)"QSPI Initialization : OK.", LEFT_MODE); } BSP_QSPI_MemoryMappedMode();
to display image use:
BSP_LCD_DrawBitmap(1, 1, (uint8_t *)(&logo));
modify the file STM32F746NGHx_FLASH.ld in the CubeWorkspace
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 307K
QSPI (xrw) : ORIGIN = 0x90000000, LENGTH = 16M <<<<<<<< add this
Memory_B1(xrw) : ORIGIN = 0x2004C000, LENGTH = 0x80
Memory_B2(xrw) : ORIGIN = 0x2004C080, LENGTH = 0x80
Memory_B3(xrw) : ORIGIN = 0x2004C100, LENGTH = 0x17d0
Memory_B4(xrw) : ORIGIN = 0x2004D8D0, LENGTH = 0x17d0
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
.textqspi : <<<<<<<<<<<<<<<<<<<<< add this section
{
. = ALIGN(4);
_qspi_start = .; /* create a global symbol at qspi start */
*(.textqspi) /* .textqspi sections */
*(.textqspi*) /* .textqspi* sections */
. = ALIGN(4);
_qspi_end = .; /* define a global symbols at end of textqspi */
} >QSPI
...................
.ARM.attributes 0 : { *(.ARM.attributes) }
.textqspi : { *(.textqspi) } >QSPI <<<<<<<<<<<<<<<< add this
.RxDecripSection : { *(.RxDescripSection) } >Memory_B1
.TxDescripSection : { *(.TxDescripSection) } >Memory_B2
.RxarraySection : { *(.RxBUF) } >Memory_B3
.TxarraySection : { *(.TxBUF) } >Memory_B4
}
Install ST-Link Server and set these options in Project/Properties/Run-Debug section
or use the external ST-LINK app with this set