주요 내용으로 건너뛰기

플래시 제한 GUI 개발

이 문서에서는 TouchGFX를 사용하여 플래시 메모리 사용량이 적은 그래픽 사용자 인터페이스를 개발하는 방법을 설명합니다.

TouchGFX를 사용하여 코드를 생성할 때, 이미지, 텍스트, 글꼴과 같은 애셋은 C++ 파일로 변환된 다음, 프로그래밍하는 동안 TouchGFX 애플리케이션 코드, 사용자 코드, TouchGFX 라이브러리와 함께 플래시 메모리에 저장됩니다. 이는 애셋이 많은 대형 프로젝트 또는 복잡한 프로젝트의 경우 플래시 사용량이 많다는 것을 뜻합니다.

대부분의 애플리케이션에서 메모리 리소스는 제한되어 있으므로 필요한 플래시 메모리 크기를 줄이는 여러 가지 방법이 있습니다. TouchGFX에는 네 가지 기본 기능이 있으며 사용자의 애플리케이션에서 필요로 하는 플래시 메모리의 크기를 상당히 줄이는 데 도움을 줍니다. 이러한 네 가지 개념은 L8 이미지 형식, 이미지 압축, 확대/축소 가능한 벡터 그래픽(SVG) 그리고 벡터 글꼴입니다.

이 문서에서는 이러한 네 가지 개념을 활용하여 애플리케이션이 사용하는 플래시 메모리의 공간을 제한하는 방법을 살펴봅니다. 측정은 STM32U5G9J-DK2를 사용하여 이루어졌지만, 플래시를 절약하는 개념은 다른 하드웨어 플랫폼에도 적용할 수 있습니다.

Further reading

메모리 관리에 대한 자세한 내용은 메모리 사용량 문서를 참조하십시오.

플래시 제한 E-bike 데모

이러한 네 가지 기능을 사용하여 TouchGFX를 사용할 때 플래시를 절약하는 방법을 시연하는 플래시 제한 E-bike 데모를 TouchGFX Designer에서 찾아볼 수 있습니다. 이 데모는 STM32U5G9J-DK2용 보드 특정 데모입니다. STM32U5G9J-DK2를 사용하여 얻는 이점은 하드웨어 가속 벡터 렌더링을 지원하는 NeoChromVG GPU를 갖췄다는 것입니다. 하지만 L8 이미지 형식과 이미지 압축은 모든 STM32 MCU에서 사용할 수 있습니다.

(L8, 압축, SVG 및 벡터 글꼴 없이) 압축되지 않은 비트맵을 사용하여 이 데모를 구현하는 경우 대략 10.5MB의 플래시 메모리를 사용합니다. 네 가지 플래시 절약 개념을 사용하여 구현하는 경우 데모는 대략 800KB의 플래시 메모리만을 사용합니다. 여기서 알 수 있듯, 상당한 크기의 플래시를 절약하는 것이 가능합니다. 데모에서는 네 가지 개념을 모두 사용하여 플래시를 92% 절약합니다.

언제 어떤 개념을 사용해야 하는가?

TouchGFX의 네 가지 플래시 절약 개념을 사용하는 방법에 대한 기술적인 정보와 가이드는 여기에서 찾아볼 수 있습니다.

이러한 네 가지 개념 모두 애플리케이션에서 필요한 플래시 메모리 크기를 줄이는 데 도움을 줄 수 있습니다. 언제 어떤 개념을 사용하는지는 상황에 따라 다르지만 몇 가지 일반적인 규칙을 적용할 수 있습니다. 이에 대해 알아보겠습니다.

L8과 압축

비트맵에서 L8 이미지 형식을 사용하는 경우 비트맵은 최대 256색을 사용할 수 있습니다. L8 형식의 애셋 렌더링은 Chrom-ART를 통해 하드웨어를 가속화할 수 있는데, 이는 L8 비트맵의 렌더링 시간이 표준 비트맵의 렌더링 시간과 거의 같다는 것을 의미합니다. 가끔은 L8 형식 비트맵을 렌더링하는 것이 표준 비트맵을 렌더링하는 것보다 빠를 수 있는데, 이는 플래시 메모리에서 읽는 데이터가 적기 때문입니다. L8은 색 심도가 32비트인 표준 비트맵과 비교했을 때 70% 이상의 플래시를 절약할 수 있습니다.

이미지 압축은 L8과 비교했을 때 더 많은 플래시를 절약하도록 도울 수 있습니다. 이미지 압축은 두 가지 형식인 L8 압축과 RGB 압축으로 제공됩니다. 비트맵에서 L8 압축을 사용하려면, 해당 비트맵이 L8 형식이어야 하는데, 이는 L8 압축 알고리즘이 Look-up 테이블을 사용하기 때문입니다. 이로 인해 L8로 압축된 비트맵은 여전히 최대 256색으로 제한됩니다. 일부 L8 압축 알고리즘에는 최대 색상 수에 대한 추가 제한이 있습니다. L4는 최대 16개의 색상으로 제한되며 L8 RLE는 최대 64개의 색상으로 제한됩니다. RGB 압축을 위해서는 비트맵이 L8 형식일 필요가 없으므로 모든 비트맵에 사용할 수 있습니다. Chrom-ART로 하드웨어가 가속화되는 L8 비트맵 렌더링과는 반대로, 압축된 비트맵(L8 압축과 RGB 압축 모두)은 소프트웨어로 렌더링되므로 렌더링에 더 많은 리소스가 소모됩니다. 압축된 비트맵은 확대/축소 또는 회전이 가능한 위젯에서 사용할 수 없다는 제약도 있습니다.

이미 가지고 있는 애셋이 PNG 형식이라면 L8 이미지 형식과 이미지 압축 모두 사용하기 쉽습니다. 일반적으로 최대 256색을 사용하는 비트맵에서는 언제든 눈에 띄는 성능 저하 없이 L8 이미지 형식을 사용할 수 있습니다. 요구되는 성능을 달성하기 위해 더 많은 플래시를 절약하고 렌더링 시간을 확보해야 하는 경우 L8 이미지 압축을 사용할 수도 있습니다. L8 형식과 호환되지 않는 비트맵을 압축하고자 할 경우 대신 RGB 압축을 사용할 수 있습니다. 확대/축소 또는 회전 가능한 위젯에서 비트맵을 사용해야 하는 경우 압축된 비트맵을 네이티브로 사용할 수 없습니다. 물론, 이 문제를 우회하는 방법이 있으며 나중에 이러한 방법을 간단히 설명하겠습니다.

SVG

애셋에서 플래시를 절약하는 다른 옵션은 PNG 형식 애셋 대신 SVG 형식 애셋을 사용하는 것입니다. SVG는 색 수에 제한이 없습니다. 하지만 SVG는 보통 L8 또는 압축과 비교했을 때 렌더링 비용이 더 듭니다. 따라서 동시에 사용되는 SVG 수를 제한하고 SVG 애니메이션을 최소화하는 것이 좋습니다. SVG 애셋이 단순할수록 플래시 사용량이 더 적고 더 높은 성능을 달성할 수 있습니다. 이에 따라 단일 계층 SVG만 사용하는 것이 좋습니다.

SVG 위젯에서 애셋을 사용하려면 해당 애셋을 SVG 형식으로 불러올 필요가 있습니다. 애셋은 TouchGFX를 사용하여 변환할 수 없습니다.

벡터 글꼴

SVG 형식의 비글꼴 애셋에 대해 이야기하자면, 벡터 글꼴 역시 렌더링에 많은 CPU 자원을 사용하게 되는데 이는 SVG와 같은 방식으로 렌더링되기 때문입니다. 벡터 글꼴은 일반적으로 글꼴 크기가 크거나 동일한 글꼴을 여러 크기로 사용할 때 이득입니다. 동일한 글꼴을 여러 크기와 벡터 표현으로 사용하더라도 글꼴을 한 번만 저장하면 됩니다. 그러면 글꼴을 다른 크기로 표현할 때 확대/축소 비율만 필요합니다. 비트맵 글꼴의 경우 각 글꼴 크기를 따로 저장해야 합니다. 벡터 글꼴은 이미지 압축이나 SVG와 비교했을 때 플래시를 크게 절약하지 못하는 경우가 종종 있습니다. 따라서 이는 플래시 메모리 사용량을 극단적으로 줄일 필요가 있을 때만 주로 사용하는 것이 좋습니다.

예시

다양한 개념의 특성에 대한 예를 구체적으로 제공하기 위해 표준 비트맵, L8, L8 RLE 압축, RGB 압축 및 SVG 형식의 E-bike 데모에서 두 개의 애셋을 측정했습니다. STM32U5G9J-DK2에서 내부 플래시에 저장된 애셋을 측정했습니다. NeoChrom GPU가 없는 MCU에서는 SVG의 렌더링 시간이 더 깁니다. 하지만 빠른 CPU 속도가 이를 보완할 수 있습니다.

아래 애셋은 색 심도가 32비트이며 상단에 아이콘이 있는 버튼입니다. 버튼은 122 x 112픽셀이며 아이콘은 72 x 72픽셀입니다.

E-bike 데모의 아이콘이 있는 버튼

애셋에 대해 다음과 같은 측정을 진행했습니다.

형식크기비율렌더링 시간CPU 부하
비트맵:75.4KB100%0.414ms2.4%
L8:19.3KB25.6%0.448ms2.3%
L8 RLE:2.55KB3.4%1.51ms9.6%
RGB:4.53KB12.0%1.65ms10.5%
SVG:3.01KB4.0%1.43ms4.1%

이를 통해 알 수 있듯이, L8 RLE는 플래시 사용량이 가장 적지만 표준 비트맵 형식과 비교했을 때 렌더링 시간이 약 1ms 더 걸립니다.

아래 애셋은 색 심도가 32비트이며 데모 대시보드 화면에 있는 게이지의 일부입니다. 이 애셋은 150 x 436픽셀입니다.

E-bike 데모 게이지의 일부

애셋에 대해 다음과 같은 측정을 진행했습니다.

형식크기비율렌더링 시간CPU 부하
비트맵:261.6KB100%1.15ms1.5%
L8:65.6KB25.1%1.24ms1.4%
L8 RLE:4.66KB1.78%2.75ms15.0%
RGB:10.5KB4.01%3.08ms17.6%
SVG:0.686KB0.27%3.40ms2.0%

SVG 형식 애셋의 플래시 사용량이 가장 낮지만 렌더링 비용이 가장 비쌉니다.

결론

위에서 알 수 있듯, 모든 애셋에서 최고인 형식은 없습니다. 하지만 플래시 절약만 놓고 보았을 때 애셋이 상대적으로 작은 경우 L8 이미지 압축이 대체로 플래시 사용량이 가장 적으며 애셋이 클 경우에는 SVG의 플래시 사용량이 가장 적습니다. SVG 애셋에서 256색 이상을 사용할 수 있지만 플래시 메모리 사용량과 성능을 모두 고려했을 때 SVG 애셋을 상대적으로 간소하게 유지하는 것이 좋습니다. L8, 이미지 압축, SVG 중에 L8 이미지 형식이 플래시 사용량은 가장 높지만 렌더링 시간이 가장 빠릅니다.

따라서 플래시가 제한된 애플리케이션을 개발할 때 병목 현상을 파악하고 애플리케이션에 가장 중요한 요소가 무엇인지 정해야 합니다. 성능이 가장 중요할 수도 있고 플래시 메모리 절약이 가장 중요할 수도 있습니다. 성능이 중요하다면 L8이 가장 효율적인 접근 방법입니다. 성능이 허락한다면 여기에 더해 일부 애셋을 압축할 수도 있습니다. 플래시 사용량을 최소화하는 것이 가장 중요하다면 이미지 압축과 SVG가 최선의 접근 방법입니다.

'스마트' 애셋 사용

'스마트' 애셋을 사용하면 플래시 사용량과 성능을 모두 개선할 수 있습니다. 여기에서 스마트 애셋은 애셋 자체와 그 사용법 모두를 의미합니다.

단순한 애셋

무엇보다도, 애셋이 단순하면 압축률이 높아지며 SVG 정의도 단순해집니다. 이는 결국 플래시 사용량 절약으로 이어집니다.

참고로, E-bike 데모에서 모든 비트맵 애셋은 최대 64개의 색상을 사용하며 이러한 애셋도 L8 RLE 압축에 적합하므로 모든 비트맵 애셋은 L8 RLE 압축되어 있습니다. L8 RLE는 L8 LZW9와 비교했을 때 렌더링이 더 빠르므로 성능도 더 우수합니다.

또한 설계가 단순하다면 경우에 따라 Tiled Image도 사용할 수 있습니다. 이렇게 하면 이미지의 일부만 저장하여 반복할 수 있습니다.

Box 위젯 사용

플래시 메모리를 스마트하게 절약하는 또 다른 방법은 Box 위젯을 사용하는 것입니다. Box를 사용하면 두 가지 이점이 있습니다.

  1. 우선 Box는 프레임 버퍼에서 직접 그립니다. 이 때문에 Box를 저장할 때 플래시 메모리가 필요하지 않습니다. 플래시에 영향을 주는 유일한 요소는 Box를 정의하기 위한 소량의 코드뿐입니다.
  2. 다음으로, Box는 조정이 가능하며 런타임으로 색과 크기를 변경할 수 있습니다. 플래시 제한 E-bike 데모에서 Box는 예를 들어 단색 배경색에서 사용되며 Box 색을 변경하는 방식으로 밝은 모드와 어두운 모드를 모두 지원합니다.

재사용 가능한 애셋

플래시 메모리를 절약하는 또 다른 방법은 총 애셋 수를 제한하는 것입니다. 이는 물론 아주 단순한 설계로 달성할 수 있지만 동일한 애셋을 여러 번 사용하여 존재하는 애셋 수를 제한할 수 있는 경우도 있습니다.

플래시 제한 E-bike 데모에서 이 접근 방법은 날씨 화면과 같은 곳에서 사용됩니다. 날씨 아이콘은 3가지 크기에 맞도록 크기가 조정되는 동일한 애셋입니다. 확대/축소되는 애셋이므로 RLE로 압축하면 플래시 사용량이 적음에도 SVG 형식이 선호됩니다. 하지만 세 가지 크기의 애셋을 모두 RLE 형식으로 저장하면 총 플래시 사용량은 더 많습니다.

추가적으로, 버튼 역시 재사용 가능 애셋으로 구현됩니다. 예를 들어, 버튼은 재사용할 수 있도록 아이콘과 분리되어 있습니다.

데모에서 재사용 가능한 애셋을 사용하는 다른 사례는 배경입니다. 데모에는 다섯 가지 배경 디자인이 있는데, 조정 가능한 애셋(박스와 재사용 가능 애셋)을 사용하여 모든 배경을 단 하나의 애셋과 박스로 생성했습니다.

성능 개선

플래시가 제한된 애플리케이션을 개발할 때는 성능이 저하될 위험이 있습니다. 하지만 여분의 RAM이 있다면 애플리케이션의 성능을 개선하는 방법이 있습니다. 동적 비트맵캐싱 가능한 컨테이너를 사용하면 애셋 또는 컨테이너의 정적 스냅샷을 RAM에 그릴 수 있습니다. 그러면 해당 애셋 또는 컨테이너를 사용할 때마다, 캐싱된 버전을 대신 사용할 수 있습니다. 캐싱된 버전은 단순히 RAM에 있는 비트맵이며 이는 렌더링 시간이 표준 비트맵 렌더링 시간과 동일하다는 뜻입니다.

플래시 제한 E-bike 데모에서는 캐싱 가능한 컨테이너를 사용하여 SVG 애셋과 벡터 글꼴의 스크롤을 가능하게 하는 동시에 좋은 성능을 유지합니다.

캐싱 가능한 컨테이너 형식의 날씨 요소

일반적으로 벡터 글꼴은 런타임에서 이동하거나 이동 가능하게 될 때마다 캐싱됩니다. 이는 벡터 글꼴을 스크롤하더라도 최소 30FPS가 유지되도록 보장합니다.

데모에서 사용되는 또 다른 요령은 압축된 비트맵을 비트맵 캐시에서 압축 해제하는 것입니다. RAM에서 압축 해제한 비트맵은 확대/축소 및 회전 가능한 위젯에서 사용할 수 있습니다. 비트맵을 압축 해제할 경우 TouchGFX는 해당 비트맵 ID를 참조할 때 항상 압축 해제되고 캐싱된 버전을 사용합니다. 아래는 E-bike 데모의 예시입니다. 압축된 비트맵은 단순히 압축 해제된 후 표준 비트맵처럼 사용됩니다.

StartView.cpp
StartView::StartView()
{
Bitmap::decompress(BITMAP_MAIN_RIPPLE_LEFT_ID); // 압축된 이미지를 비트맵 캐시에서 압축 해제
Bitmap::decompress(BITMAP_MAIN_RIPPLE_RIGHT_ID); // 압축된 이미지를 비트맵 캐시에서 압축 해제
}

void StartView::setupScreen()
{
leftMainRippleScale.setBitmap(BITMAP_MAIN_RIPPLE_LEFT_ID); // 비트맵을 확대/축소 가능한 이미지로 설정
rightMainRippleScale.setBitmap(BITMAP_MAIN_RIPPLE_RIGHT_ID); // 비트맵을 확대/축소 가능한 이미지로 설정
leftMainRippleScale.setWidthHeight(0, 0); // 이미지 크기 설정
rightMainRippleScale.setWidthHeight(0, 0); // 이미지 크기 설정
}

동적 비트맵을 광범위하게 사용한 결과 플래시 제한 E-bike 데모는 922KB의 비트맵 캐시를 요구합니다. 이는 여분의 RAM이 많이 필요하다는 의미입니다. 하지만 데모에서는 극단적인 플래시 절약도 추구합니다. 더 단순한 애플리케이션 또는 성능 요구 사항이 그렇게 중요하지 않은 애플리케이션에서는 비트맵 캐시가 더 적어도 큰 문제가 발생하지 않습니다.

결론

이 문서에서는 TouchGFX 애플리케이션에서 플래시 사용량을 제한하는 방법을 살펴보았습니다.

플래시를 절약하는 네 가지 방법은 모든 STM32 하드웨어 플랫폼에서 사용할 수 있지만 SVG와 벡터 글꼴은 렌더링에 더 많은 CPU 자원을 사용한다는 점을 염두에 두어야 합니다. 이런 방법을 사용할 때 벡터 렌더링의 하드웨어 가속이 없거나 사용 가능한 추가 컴퓨팅 파워가 없다면 성능이 떨어질 수 있습니다.

플래시 제한 GUI 개발 개념은 성능 저하로 이어질 수 있지만 동적 비트맵과 캐싱 가능한 컨테이너를 사용하여 성능을 개선할 수 있습니다.

플래시 절약 개념을 사용하면 잠재적으로 대량의 플래시를 절약할 수 있습니다. 이러한 개념이 절약할 수 있는 플래시의 정확한 양은 애플리케이션에 따라 다르지만 플래시 제한 E-bike 데모에서는 플래시 92% 절약을 달성했습니다.