주요 내용으로 건너뛰기

이미지와 글꼴에서 직렬 플래시 사용

이 섹션에서는 직렬 플래시(또는 기타 매핑되지 않은 스토리지)를 사용하여 이미지와 글꼴을 저장하는 방법을 설명합니다. 여기에 설명된 기술은 STM32G0과 RAM 용량이 매우 작은 기타 디바이스에서 특히 유용합니다.

직렬 플래시와 함께 종종 사용되는 부분 프레임 버퍼에 대한 내용은 부분 프레임 버퍼로 메모리 사용량 줄이기 문서를 참조하십시오. 또한, 매핑되지 않은 플래시에서 RAM으로 비트맵을 캐싱하는 방법에 대한 내용은 이미지 저장을 위해 비메모리 매핑 플래시 사용 문서를 참조하십시오.

구성

TouchGFX 애플리케이션에서 직렬 플래시를 사용하려면 "Additional Features"에서 "External Data Reader"를 활성화하도록 TouchGFX Generator 구성을 변경해야 합니다.

Additional Features: Data Reader

이 기능을 활성화하면 TouchGFX Generator는 LCD16bppSerialFlash LCD 클래스를 사용하도록 구성을 변경합니다. 또한 touchgfx::FlashDataReader의 하위 클래스를 생성합니다.

TouchGFXConfiguration.cpp
static TouchGFXDataReader dataReader;
static LCD16bppSerialFlash display(dataReader);
static ApplicationFontProvider fontProvider;
...
void touchgfx_init()
{
...
hal.setDataReader(&dataReader);
fontProvider.setFlashReader(&dataReader);
...
}

이 코드는 TouchGFXDataReader 클래스의 인스턴스를 생성하고, 해당 인스턴스를 디스플레이 객체, HAL 객체 및 ApplicationFontProvider 객체에 전달합니다. 이들 세 가지 객체는 dataReader 객체를 사용하여 직렬 플래시의 데이터에 액세스합니다. 이미지 데이터와 글꼴 데이터 모두 데이터가 될 수 있습니다.

시스템 프로그래머가 실제로 플래시에서 데이터를 읽을 수 있으려면 TouchGFXDataReader 클래스의 구현을 완료해야 합니다.

구현

TouchGFXDataReader 클래스는 touchgfx::FlashDataReader 인터페이스를 구현합니다. 이 인터페이스의 경우, 특정 하드웨어에서 다음과 같은 4개의 메소드를 구현해야 합니다.

include/touchgfx/hal/FlashDataReader.hpp
    bool addressIsAddressable(const void* address)
void copyData(const void* src, void* dst, uint32_t bytes)
void startFlashLineRead(const void* src, uint32_t bytes)
const uint8_t* waitFlashReadComplete()

addressIsAddressable 메소드는 LCD16bppSerialFlash 클래스가 일부 데이터에 대해 직접 읽기를 수행할 수 있는지(내부 RAM 또는 내부 플래시에 저장되어 있는지), 아니면 dataReader 객체를 통해 읽기를 수행해야 하는지를 결정하는 데 사용됩니다.

copyData*` 메소드는 플래시에서 RAM으로 데이터를 동기식으로 복사하는 데 사용됩니다. 이 함수는 보통 데이터가 추가 처리되지 않을 사용됩니다. 예를 들면 솔리드 이미지를 프레임 버퍼에 복사할 때 사용됩니다.

startFlashLineRead 메소드는 플래시에서 여러 라인의 데이터가 필요할 때 사용됩니다. startFlashLineRead 메소드는 데이터 읽기를 개시합니다. 이 메소드는 비동기식 읽기 작업을 개시할 수 있으며, 읽기가 시작되면 즉시 값을 반환해야 합니다. waitFlashReadComplete 메소드는 읽기가 완료될 때까지 기다려야 하며, 데이터를 보유하고 있는 버퍼에 포인터를 반환해야 합니다.

LCD16bppSerialFlash는 상황에 따라 이전에 읽은 데이터를 처리하는 동안 하나의 플래시 읽기를 발행할 수 있습니다. 따라서 완전한 동시성을 달성하기 위해서는 dataReader에 버퍼가 두 개 이상 필요합니다.

TouchGFX Generator는 TouchGFXGeneratedDataReaderTouchGFXDataReader의 두 가지 클래스에서 FlashDataReader를 생성합니다. TouchGFXGeneratedDataReader는 두 클래스의 슈퍼 클래스로, 기본 실행을 포함합니다. 이 실행이 적합하지 않은 경우, 애플리케이션 프로그래머는 TouchGFXDataReader 클래스에서 구현된 가상 함수를 변경할 수 있습니다.

TouchGFXGeneratedDataReader 실행은 이 작업을 수행하기 위해 C 함수를 호출합니다. 이들 애플리케이션은 시스템 프로그래머가 구현합니다.

TouchGFX/target/generated/TouchGFXGeneratedDataReader.cpp
extern "C" __weak void DataReader_WaitForReceiveDone();
extern "C" __weak void DataReader_ReadData(uint32_t address24, uint8_t* buffer, uint32_t length);
extern "C" __weak void DataReader_StartDMAReadData(uint32_t address24, uint8_t* buffer, uint32_t length);

void TouchGFXGeneratedDataReader::startFlashLineRead(const void* src, uint32_t bytes)
{
/* Start transfer using DMA */
DataReader_StartDMAReadData((uint32_t)src, (readToBuffer1 ? buffer1 : buffer2), bytes);
}

구현된 결과는 MB1642BDataReader.c 파일에서 찾을 수 있습니다.

Core/Src/MB1642BDataReader.c
void DataReader_StartDMAReadData(uint32_t address24, uint8_t* buffer, uint32_t length)
{
readDataDMA(address24, buffer, length);
}

void readDataDMA(uint32_t address24, uint8_t* buffer, uint32_t length)
{
// Pull Flash CS pin low
isReceivingData = 1;
FLASH_CS_GPIO_Port->BRR = FLASH_CS_Pin;

*((__IO uint8_t*)&hspi2.Instance->DR) = CMD_READ;

...
}

이러한 구현은 플래시에서 사용하는 프로토콜과 SPI 및 CS에서 사용하는 GPIO에 한 합니다. TouchGFXGeneratedDataReader 클래스가 작동하려면 세 가지 C 함수를 모두 구현해야 합니다.

이미지

서론에서 언급했듯이 LCD16bppSerialFlash 클래스는 dataReader 객체를 통해 이미지 픽셀을 읽을 수 있습니다. 이를 위해 내부 플래시 범위 밖의 주소 범위에 이미지를 저장하도록 링커 스크립트를 변경해야 합니다.

STM32G071에서는 직렬 플래시의 시작 주소로 0x90000000 주소를 선택했습니다.

gcc/STM32G071RBTX_FLASH.ld
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 36K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
SPI_FLASH (r) : ORIGIN = 0x90000000, LENGTH = 8M
}

/* Sections */
SECTIONS
{
...

ExtFlashSection :
{
*(ExtFlashSection ExtFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >SPI_FLASH

FontFlashSection :
{
*(FontFlashSection FontFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >SPI_FLASH
}

이렇게 하면 ExtFlashSectionFontFlashSection이 0x90000000 주소 범위 내에 저장됩니다.

이제 플래시 도구를 사용하여 외부 플래시에 데이터를 기록하는 작업만 남았습니다.

STM32CubeProgrammer용 플래시 로더를 작성하는 방법은 이 문서의 섹션 2.3.3 UM2237 STMCubeProgrammer 사용자 매뉴얼에서 확인하실 수 있습니다.

글꼴 데이터

위의 링커 스크립트는 글꼴 픽셀 데이터와 글꼴 문자 메타 데이터(너비 및 높이)를 외부 플래시에 저장합니다(두 유형의 데이터 모두 FontFlashSection에 저장). 화면에 문자를 그려 넣을 때 dataReader 객체를 통해서도 이 데이터를 읽을 수 있습니다.

"Unmapped Storage Format"을 사용하고 있지 않은 경우에는 링커 스크립트와 include/touchgfx/hal/Config.hpp 파일을 변경해 글꼴 문자 메타 데이터를 내부 플래시로 옮겨야 합니다.

글꼴 형식에 대한 자세한 내용은 매핑되지 않은 스토리지의 글꼴에 대한 문서를 참조하십시오.