對字體資料使用非記憶體映射快閃記憶體
本節將討論如何使用未映射的字體存儲格式,以便將幾乎所有的字體資料放入未映射的外部快閃記憶體。 使用該存儲格式的效果是,您可以在一個應用程式中有數千個字母,而字體資料只需10 KB的內部flash存儲空間。
字體佈局
對於編譯到應用中的字體,TouchGFX支援兩種不同的字體佈局。 在TouchGFX Designer的配置選項卡中選擇要使用的佈局:
映射存儲格式
是預設字體佈局,應當用在將字體存儲在記憶體映射快閃記憶體(內部或外部QSPI快閃記憶體等)中的系統上。
未映射存儲格式
是最新的字體佈局。 它可以將大多數字體資料存儲在未映射快閃記憶體中。 這通常是SPI快閃記憶體,但可以是任何類型的存儲。
映射存儲格式
映射存儲格式將字體資料保存在兩個表中。
第一個表是一個 touchgfx::GlyphNode陣列。 其中包含各個字元的屬性:高、寬和unicode等。
generated/fonts/src/Table_verdana_20_4bpp.cpp
FONT_TABLE_LOCATION_FLASH_PRAGMA
KEEP extern const touchgfx::GlyphNode glyphs_verdana_20_4bpp[] FONT_TABLE_LOCATION_FLASH_ATTRIBUTE =
{
{ 0, 0x0020, 0, 0, 0, 0, 7, 0, 0, 0x00 },
{ 0, 0x002C, 5, 7, 3, 1, 7, 0, 2, 0x00 },
{ 21, 0x0030, 11, 14, 14, 1, 13, 0, 0, 0x00 },
{ 105, 0x0032, 11, 14, 14, 1, 13, 0, 0, 0x00 },
{ 189, 0x0033, 11, 14, 14, 1, 13, 0, 0, 0x00 },
{ 273, 0x0034, 12, 14, 14, 0, 13, 0, 0, 0x00 },
...
}
第二個表(分為多個檔的大字體)包含字元的像素模式。
generated/fonts/src/Font_verdana_20_4bpp_0.cpp
FONT_GLYPH_LOCATION_FLASH_PRAGMA
KEEP extern const uint8_t unicodes_verdana_20_4bpp_0[] FONT_GLYPH_LOCATION_FLASH_ATTRIBUTE =
{
// Unicode: [0x0020]
// (Has no glyph data)
// Unicode: [0x002C]
0x00, 0x87, 0x04, 0x20, 0xFF, 0x03, 0x60, 0xBF, 0x00, 0xA0, 0x5F, 0x00, 0xE0, 0x0D, 0x00, 0xF3,
0x07, 0x00, 0xF6, 0x01, 0x00,
// Unicode: [0x0030]
0x00, 0xA3, 0xFE, 0x9D, 0x01, 0x00, 0x40, 0xFF, 0x9B, 0xFC, 0x1D, 0x00, 0xD0, 0x4F, 0x00, 0x80,
0x9F, 0x00, 0xF3, 0x0B, 0x00, 0x10, 0xEE, 0x00, 0xF7, 0x07, 0x00, 0x00, 0xFB, 0x03, 0xF9, 0x06,
...
}
在文字佈局的過程中,TouchGFX引擎將使用GlyphNodes。 在繪圖過程中,像素將由DMA2D或軟體讀取。
在使用普通LCD分類(如LCD16bpp或LCD24bpp)的平臺上,必須將這些表保存在內部Flash或記憶體映射的外部Flash中。
在使用LCD16bppSerialFlash的平臺上,渲染軟體可以從未映射的串列快閃記憶體中讀取像素型樣,但GlyphNodes表必須位於內部flash中(直接搜索)。
該佈局為每個字元使用14個位元組的內部flash。
未映射存儲格式
未映射存儲格式將字體資料保存在三個表中。 重複使用了來自映射存儲佈局的兩個表,但增加了第三個表:
generated/fonts/src/Table_verdana_20_4bpp.cpp
FONT_SEARCHTABLE_LOCATION_FLASH_PRAGMA
KEEP extern const uint16_t unicodelist_verdana_20_4bpp[] FONT_SEARCHTABLE_LOCATION_FLASH_ATTRIBUTE =
{
0x0020,
0x002E,
0x003F,
0x004E,
0x0054,
....
}
這第三個表只包含字體中出現的unicodes 。
在使用此字體佈局時,第三個表必須位於內部Flash中,但可以將另外兩個表移動到外部Flash中。 由於第三個表對每個字元使用2個位元組,而GlyphNode表使用14個位元組,因此大大節約了存儲空間。 這可以降低內部快閃記憶體的存儲要求。
字體資料讀取器
當字體資料位於未映射快閃記憶體中時,MCU不能直接存取它。 因此,我們必須為字體子系統提供Flash的讀取物件。
相關程式碼由TouchGFXGenerator自動生成:
TouchGFXConfiguration.cpp
static TouchGFXDataReader dataReader;
static LCD16bppSerialFlash display(dataReader);
static ApplicationFontProvider fontProvider;
static Texts texts;
static TouchGFXHAL hal(dma, display, tc, 240, 320);
void touchgfx_init()
{
Bitmap::registerBitmapDatabase(BitmapDatabase::getInstance(), BitmapDatabase::getInstanceSize());
TypedText::registerTexts(&texts);
Texts::setLanguage(0);
hal.setDataReader(&dataReader);
fontProvider.setFlashReader(&dataReader);
...
如果您不使用生成器,則必須手動操作。
注意,應實現 TouchGFXDataReader 中的功能,從而實際上從快閃記憶體中讀取資料。
總結
字體資料保存在兩個或三個表中。 下表顯示了flash中的位置:
表(範例名稱) | 映射存儲格式 | 未映射存儲格式 |
---|---|---|
GlyphNodes in glyphs_verdana_20_4bpp | 內部 | 外部 |
像素資料位於unicodes_verdana_20_4bpp_0中 | 外部 | 外部 |
Unicodes位於unicodelist_verdana_20_4bpp中 | 未使用 | 內部 |
範例
下面是使用新字體佈局的應用的螢幕截圖:
此應用運行在具有MB1642A顯示模組的STM32G071 Nucleo板上:
在該應用中,有4000個大小為20、每像素4位元的中文字元。 應用程式和資料佔用了STM32G071上128 Kb可用存儲空間中的61 Kb。 字體資料分配如下(不包括次要物件):
表 | 位置 | 大小 |
---|---|---|
GlyphNodes | 外部SPI快閃記憶體 | 57.372位元組 |
像素模式 | 外部SPI快閃記憶體 | 3.116.296位元組 |
unicode表 | 內部Flash | 8.000位元組 |
連結腳本修改
為了正確地使用未映射字體佈局,您必須更新連結腳本,以便正確地放置表格。
STM32F746.ld
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x0801FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20008FFF;
define symbol __ICFEDIT_region_SERIAL_FLASH_start__ = 0x90000000;
define symbol __ICFEDIT_region_SERIAL_FLASH_end__ = 0x91000000;
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block HEAP };
place in SERIAL_FLASH_region {section ExtFlashSection, section FontFlashSection };
在該連結腳本中,我們將ExtFlashSection(圖像和字體像素)和FontFlashSection(GlyphNodes)都放在外部快閃記憶體中。 任何其他唯讀資料都位於內部快閃記憶體(ROM_region)中。