SPI 디스플레이 인터페이스
이 시나리오는 SPI 직렬 인터페이스와 GRAM이 탑재된 디스플레이를 사용할 때 SPI와 TouchGFX Generator를 구성하는 방법을 설명합니다.
Note
구성
SPI 구성
SPI는 다른 디스플레이 인터페이스(예: FMC)에 비해 대역폭이 낮습니다. 따라서 대역폭을 극대화하기 위해 SPI 구성을 최고 수준의 보율(Baud rate)로 최적화하는 것이 중요합니다. STM32CubeMX 카테고리 목록의 Connectivity 그룹에서 SPI를 활성화합니다. CPU 부하를 최소화하기 위해 DMA 채널을 SPI로 구성하는 것이 좋습니다. 아래 예제는 64MHz MCU에 대한 것으로, SPI 보(Baud)의 상한은 32MBit/s로 설정되어 있습니다.
디스플레이와 일치하도록 클록 매개변수를 구성해야 합니다.
TouchGFX Generator
SPI 디스플레이 인터페이스를 사용하는 경우 TouchGFX Generator에서 Custom Display Interface를 선택해야 합니다. 이는 전체 HAL은 자동으로 생성될 수 없으므로 개발자가 프레임 버퍼 메모리에서 픽셀을 구성하여 수동으로 디스플레이로 전송해 기능을 구현해야 한다는 뜻입니다. 이를 달성하는 데 필요한 모든 핸들은 TouchGFX Generator에 의해 생성됩니다:
DMA 구성
CPU 부하를 최소화하기 위해 픽셀 데이터가 프레임 버퍼에서 SPI TX 주소로 전송되도록 DMA 채널을 구성할 수 있습니다.
사용자 코드
일반적으로 임베디드 GRAM이 탑재된 디스플레이의 경우 TouchGFXHAL.cpp
에서 생성된 TouchGFX HAL 핸들을 구현하려면 다음 단계를 수행해 픽셀을 디스플레이로 전송하고 디스플레이를 TouchGFX Engine과 동기화해야 합니다:
- "VSYNC"(TE(Tearing Effect) 신호라고도 불림)가 TouchGFX Engine에 신호를 보낼 때까지 대기합니다.
- 다시 그려질 프레임 버퍼의 영역을 기준으로 "디스플레이 커서"와 "활성 창"(업데이트되는 디스플레이의 영역)을 이 영역과 일치하는 GRAM의 위치로 이동시킵니다.
- GRAM에 입력되는 픽셀 데이터를 기록할 준비를 합니다. 사용되는 프레임 버퍼 전략과 디스플레이 인터페이스에 따라 이는 프레임 버퍼 포인터를 바꾸거나, TouchGFX Engine에 신호를 보내거나, 이전 전송이 완료될 때까지 기다릴 수도 있습니다.
- 픽셀 데이터를 전송합니다.
어떤 디스플레이를 사용하고 프레임 버퍼 전략이 무엇인지에 따라 위 단계의 구현이 달라질 수 있습니다.
지원되는 프레임 버퍼 전략
- 단일
- 이중
- 부분 - GRAM 디스플레이(권장)
Further reading
SPI를 통해 달성되는 대역폭은 다른 디스플레이 인터페이스에 비해 제한적이므로 '부분 - GRAM 디스플레이' 전략을 사용하는 것이 좋습니다. 이 전략에는 매우 적은 양의 RAM을 사용한다는 장점이 있으며(제한된 RAM이 장착된 단순한 시스템에는 보통 SPI가 사용됨) 업데이트된 픽셀을 포함하는 디스플레이로 전송을 시작하는 것을 통해서만 가용 대역폭의 사용이 최적화됩니다. 하지만 깨짐 현상이 발생할 위험이 있습니다.
SPI와 함께 단일 버퍼링을 사용하면 긴 렌더링으로 인한 깨짐 현상을 방지할 수 있습니다. 하지만 SPI의 낮은 대역폭은 일반적으로 픽셀을 디스플레이로 전송하는 속도가 디스플레이 주사선이 GRAM 버퍼를 읽는 속도보다 느리다는 것을 의미합니다. 이로 인해, 깨짐을 방지하기 위해서는 디스플레이가 활성 영역에 진입할 때 TE 신호의 하강 엣지에서 전송을 시작하는 것이 중요합니다. 이는 다음과 같은 형태일 수 있습니다:
TouchGFXHAL.cpp
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == LCD_TE_Pin)
{
// VSync has occurred, increment TouchGFX engine vsync counter
HAL::getInstance()->vSync();
// VSync has occurred, signal TouchGFX engine
OSWrappers::signalVSync();
GPIO::clear(GPIO::VSYNC_FREQ);
if (refreshRequested)
{
refreshRequested = false;
nextSendToDisplayLine = refreshMinLine;
maxSendToDisplayLine = refreshMaxLine;
sendNextFrameBufferBlockToDisplay();
}
}
}
Note
SPI와 함께 이중 버퍼링을 사용하면 긴 렌더링으로 인한 깨짐 현상을 방지할 수 있습니다. 하지만 각 프레임에서 너무 많은 픽셀이 디스플레이로 전송될 경우 GRAM 버퍼를 읽는 주사선이 전송되는 영역과 충돌하여 느린 전송 대역폭으로 인한 깨짐이 발생할 수 있습니다. 이는 전체 프레임 버퍼가 아닌 업데이트된 픽셀 영역만 전송하는 것을 통해 완화할 수 있습니다. 각 프레임에서 업데이트된 영역을 계산하여 최소 전송 영역을 정의하는 데 TouchGFXHAL::flushFrameBuffer
함수를 사용할 수 있습니다.
단일
현재 어떤 TouchGFX Board Support에도 SPI와 함께 사용하는 단일 버퍼링에 대한 참조 구현은 없습니다. 설정은 FMC 단일 버퍼 설정과 유사하나 FMC 대신 SPI 드라이버 기능을 사용합니다.
이중
현재 어떤 TouchGFX Board Support에도 SPI와 함께 사용하는 이중 버퍼링에 대한 참조 구현은 없습니다. 설정은 FMC 이중 버퍼 설정과 유사하나 FMC 대신 SPI 드라이버 기능을 사용합니다.
부분 - GRAM 디스플레이
TouchGFX Board Setup NUCLEO-G071RB + GFX01M2에는 SPI가 탑재된 부분 - GRAM 디스플레이의 참조 구현이 포함됩니다. 설정은 FMC 부분 버퍼 설정과 유사하나 FMC 대신 SPI 드라이버 기능을 사용합니다: