글꼴 데이터에 메모리 매핑 모드가 아닌 플래시 사용
이 섹션에서는 새로운 글꼴 레이아웃을 사용하여 거의 모든 글꼴 데이터를 매핑되지 않은 외부 플래시에 넣는 방법을 살펴보겠습니다. 50KB에 불과한 플래시를 사용하여 애플리케이션에 수 천 개의 문자를 가질 수 있는 효과가 있습니다.
글꼴 레이아웃
TouchGFX는 애플리케이션에 컴파일된 글꼴에 대해 두 가지 글꼴 레이아웃을 지원합니다. Configurations 탭의 TouchGFX Designer에서 사용할 레이아웃을 선택합니다.
매핑 스토리지 형식
은 기본 글꼴 레이아웃으로, 글꼴이 메모리 매핑 플래시(내부 또는 외부 QSPI 플래시)에 저장되는 시스템에서 사용해야 합니다.
매핑되지 않은 스토리지 형식
은 새로운 글꼴 레이아웃입니다. 이 형식에서는 대부분의 글꼴 데이터를 매핑되지 않은 플래시에 저장할 수 있습니다. 보통은 SPI 플래시이지만, 어떤 유형의 스토리지든 사용이 가능합니다.
매핑 스토리지 형식
매핑 스토리지 형식은 두 개의 테이블에 글꼴 데이터를 보관합니다.
첫 번째 테이블은 touchgfx::GlyphNode의 배열입니다. 여기에는 높이, 너비, 유니코드 같은 개별 문자의 속성이 포함되어 있습니다.
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,
...
}
GlyphNode는 텍스트 레이아웃 시 TouchGFX 엔진에서 사용됩니다. 그리기를 하는 동안 DMA2D 또는 소프트웨어 루틴에서 픽셀을 읽습니다.
일반 LCD 클래스(LCD16Bpp 또는 LCD24Bpp)를 사용하는 플랫폼에서는 이러한 테이블들을 반드시 내부 플래시나 메모리 매핑 외부 플래시에 저장해야 합니다.
매핑되지 않은 외부 플래시를 사용하는 플랫폼에서 LCD16BppSerialFlash는 매핑되지 않은 직렬 플래시에서 픽셀 패턴을 읽을 수 있지만, GlyphNode는 내부 플래시에 있어야 합니다.
매핑되지 않은 스토리지 형식
매핑되지 않은 스토리지 형식은 글꼴 데이터를 세 개의 테이블로 분할합니다. 매핑 스토리지 레이아웃에서 나온 두 개의 테이블이 재사용되지만, 세 번째 테이블은 추가됩니다.
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,
....
}
이 세 번째 테이블에는 글꼴에 있는 유니코드만 포함되어 있습니다.
이 글꼴 레이아웃을 사용할 때 세 번째 테이블은 반드시 내부 플래시에 있어야 하지만, 나머지 두 테이블은 외부 플래시로 이동이 가능합니다. 세 번째 테이블은 각 문자에 2바이트를 사용하는 반면, GlyphNode 테이블은 14바이트를 사용한다는 점에서 상당한 절감 효과가 있습니다. 따라서 내부 플래시의 저장 요구 사항이 줄어듭니다.
글꼴 데이터가 매핑되지 않은 플래시에 저장되면 MCU가 이를 직접 액세스할 수 없습니다. 따라서 글꼴 하위 시스템에 플래시 판독기 객체를 제공해야 합니다.
이에 대한 코드는 TouchGFX Generator에서 자동 생성됩니다.
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);
...
TouchGFX Generator를 사용하지 않는 경우에는 수동으로 생성해야 합니다.
TouchGFXDataReader에서 함수를 구현해야만 플래시에서 데이터를 실제로 읽을 수 있습니다.
예제
다음은 새 글꼴 레이아웃을 사용하는 애플리케이션의 스크린샷입니다.
이 애플리케이션은 MB1642A 디스플레이 모듈이 장착된 STM32G071 Nucleo 보드에서 실행됩니다.
이 애플리케이션에는 20비트(픽셀당 4비트) 크기의 한자 4000자가 있습니다. 애플리케이션과 데이터는 STM32G071에서 사용 가능한 128KB 중 61KB를 차지합니다. 글꼴 데이터는 다음과 같이 배포됩니다(마이너 객체 제외).
테이블 | 위치 | 크기 |
---|---|---|
GlyphNodes | 외부 SPI 플래시 | 57,372 바이트 |
픽셀 패턴 | 외부 SPI 플래시 | 3.116.296 바이트 |
유니코드 목록 | 내부 플래시 | 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)에 있습니다.