跳轉到主要內容

快閃記憶體受限的GUI開發

本文說明如何在使用少量快閃記憶體的情況下以TouchGFX開發圖形使用者介面。

使用TouchGFX產生程式碼時,圖像、文字及字型等資產會轉換為C++檔案,然後在程式設計期間與TouchGFX應用程式碼、使用者程式碼及TouchGFX庫一同儲存在快閃記憶體中。 因此如果是具有眾多資產的大型或複雜專案,將會使用大量快閃記憶體。

由於大部分應用程式的記憶體資源都有限,有一些方法可以減少所需的快閃記憶體容量。 TouchGFX有四種內建功能,可協助您大幅減少應用程式所需的快閃記憶體容量。 這四種概念為L8圖像格式、圖像壓縮、可縮放向量圖形(SVG)及向量字型。

本文將介紹如何使用這四種概念,以限制應用程式的快閃記憶體佔用空間。 測量是以STM32U5G9J-DK2執行,不過節省快閃記憶體的概念也可應用於其他硬體平台。

Further reading

Read the Memory Usage article for more information on memory management.

快閃記憶體受限的電動自行車示範

快閃記憶體受限的電動自行車示範,展示如何使用前述四種功能以TouchGFX節省快閃記憶體;您可在TouchGFX Designer之中參考此示範。 此示範為開發板專屬示範,適用於STM32U5G9J-DK2。 使用STM32U5G9J-DK2的優點之一就是其中具有NeoChromVG GPU,由硬體加速向量渲染。 不過L8圖像格式及圖像壓縮特別適合在所有STM32 MCU使用。

如果此示範僅以未壓縮的點陣圖實作(無L8、壓縮、SVG及向量字型),可能會佔用約10.5 MB的快閃記憶體。 在使用四種概念節省快閃記憶體的實作中,此示範僅佔用約800 KB的快閃記憶體。 由此可見,節省大量快閃記憶體是可能做到的。 這四種概念在示範中合計節省了92%的快閃記憶體空間。

各種概念的使用時機

以下是如何以TouchGFX使用四種概念節省快閃記憶體的技術資訊和指南:

這四種概念都能協助減少應用程式所需的快閃記憶體容量。 每種概念的使用時機需視情境而定,不過有些一般規則可供參考。 以下將進行說明。

L8及壓縮

在點陣圖使用L8圖像格式時,點陣圖最多會有256種色彩。 The rendering of assets in L8 format is hardware accelerated with Chrom-ART, meaning that the render time for L8 bitmaps are almost the same as for regular bitmaps. 有時渲染L8格式點陣圖的速度甚至比一般點陣圖更快,原因是從快閃記憶體讀取的資料較少。 相較於色深32位元的一般點陣圖,L8可節省70%以上的快閃記憶體。

相較於L8,圖像壓縮可讓您節省更多快閃記憶體。 Image compression comes in two formats: L8 compression and RGB compression. To use L8 compression on a bitmap, the bitmap needs to be in L8 format first, since the L8 compression algorithms use the color look-up table. As a result of this, L8 compressed bitmaps are still limited to a maximum of 256 colors. Some of the L8 compression algorithms have further limitations on the maximum number of colors. L4 is limited to a maximum of 16 colors and L8 RLE is limited to a maximum of 64 colors. RGB compression doesn't require the bitmap to be in L8 format and can hence be used on all bitmaps. Opposed to rendering of L8 bitmaps, which are hardware accelerated with Chrom-ART, compressed bitmaps (both L8- and RGB compressed) are software rendered and are hence more expensive to render. 壓縮點陣圖的另一項限制,則是無法用於可縮放或可旋轉的小工具。

如果您的資產已經採用PNG格式,則L8圖像格式及圖像壓縮都易於使用。 一般來說,您在最多256色的點陣圖上一律使用L8圖像格式,不會造成任何顯著的效能影響。 If you need to save even more flash and have available render time to achieve the required performance, you could use L8 image compression as well. If you want to compress bitmaps that are not compatible with L8 format, you can use RGB compression instead. If you need to use your bitmap in scalable or rotatable widgets, you can't use compressed bitmaps natively. 當然我們有方法可以解決這項問題,稍後將簡短說明。

SVG

在資產節省快閃記憶體的另一種選項,就是讓資產採用SVG格式取代PNG格式。 SVG對色彩數量並無限制, 不過SVG的渲染成本通常高於L8及壓縮, 因此建議限制SVG數量,並盡量減少SVG動畫數量。 SVG資產越簡單,所佔用的快閃記憶體就越少,因此可達成更理想的效能。 為此我們建議僅使用單層SVG。

若要在SVG小工具使用資產,您需要匯入SVG格式的資產。 TouchGFX無法轉換資產。

向量字型

對於SVG格式的非字型資產,向量字型也需負擔昂貴的渲染成本,因為其渲染方式與SVG相同。 向量字型一般有利於使用大型字型,或使用多種不同大小的相同字型。 如果您有不同大小及向量表示的相同字型,只需要儲存字型一次即可。 之後您只需要一個縮放係數,即可呈現不同大小的字型。 如果是點陣圖字型,每種字型大小都需要個別儲存。 向量字型所節省的快閃記憶體,通常不及圖像壓縮及SVG所節省的多。 因此主要是在必須盡可能減少使用快閃記憶體的情況下,才應使用此項方法。

範例

To provide specific examples of the characteristics of the different concepts, measurements are performed on two assets from the E-bike demo in regular bitmap, L8, L8 RLE compressed, RGB compressed and SVG-format. 我們在STM32U5G9J-DK2針對內部快閃記憶體之中的資產進行測量。 對於沒有NeoChrom GPU的MCU,SVG的渲染時間較長, 不過速度更快的CPU也可為此提供補償。

以下資產的色深為32位元,是頂端具有圖示的按鈕。 按鈕為122 x 112 px,圖示為72 x 72 px。

電動自行車示範的含圖示按鈕

以下是在資產執行的測量結果:

格式大小百分比渲染時間CPU負載
點陣圖:75.4 KB100%0.414 ms2.4%
L8:19.3 KB25.6%0.448 ms2.3%
L8 RLE:2.55 KB3.4%1.51 ms9.6%
RGB:4.53 KB12.0%1.65 ms10.5%
SVG:3.01 KB4.0%1.43 ms4.1%

As seen from this, L8 RLE has the lowest flash footprint, but takes approximately 1 ms longer to render compared to regular bitmap format.

以下資產色深32位元,是示範儀表板螢幕中儀錶的一部分, 尺寸為150 x 436 px。

電動自行車示範儀錶的一部分

以下是在資產執行的測量結果:

格式大小百分比渲染時間CPU負載
點陣圖:261.6 KB100%1.15 ms1.5%
L8:65.6 KB25.1%1.24 ms1.4%
L8 RLE:4.66 KB1.78%2.75 ms15.0%
RGB:10.5 KB4.01%3.08 ms17.6%
SVG:0.686 KB0.27%3.40 ms2.0%

SVG格式資產佔用的快閃記憶體遠低於其他格式,不過渲染成本也是最高。

結論

如前所見,沒有哪一種格式是所有資產的最佳選擇。 However, for flash saving alone, L8 image compression generally has the smallest flash footprint when the asset is relatively small, and SVG has the smallest flash footprint when the asset is larger. 雖然SVG資產可擁有256種以上色彩,但為了快閃記憶體使用量及效能因素,還是建議讓SVG資產保持簡單。 L8圖像格式在L8、圖像壓縮及SVG之中所佔用的快閃記憶體最多,不過渲染時間最短。

因此在開發快閃記憶體受限的應用程式時,您需要找出瓶頸,並決定應用程式最重要的考量因素為何。 是效能比較重要,還是節省快閃記憶體比較重要? 如果效能比較重要,L8就是最有效的方法。 如果效能允許的話,您甚至可以在部分資產合併使用壓縮方法。 如果盡可能減少使用快閃記憶體最重要,圖像壓縮及SVG就是最理想的方法。

使用「聰明的」資產

使用所謂的「聰明的」資產可節省更多快閃記憶體及提升效能。 本文所述的聰明的資產,是指資產本身及其使用方式。

簡易資產

首先,資產越簡單,所能壓縮的程度就越高,SVG定義也會更簡單, 最終可減少使用快閃記憶體。

As a reference, in the E-bike demo all bitmap assets have a maximum of 64 colors and since the assets are also well-suited for L8 RLE, all the bitmap assets are L8 RLE compressed. Since L8 RLE is faster to render compared to L8 LZW9, this also gives the best performance.

Additionally, if the design is also simple, you can in some cases use a Tiled Image as well. 之後您只需要儲存部分圖像並加以重複即可。

使用方塊

Another way of saving flash memory in a smart way is to use the Box widget. 使用方塊有兩種主要優點:

  1. 首先方塊可在影像緩衝區直接繪製, 因此無需快閃記憶體即可儲存方塊。 唯一會用到快閃記憶體的部分,就是定義方塊所需的少量程式碼。
  2. 第二,方塊可調整,並可於執行階段變更色彩及大小。 在快閃記憶體受限的電動自行車示範中,方塊用於實心背景色彩等範例,透過變更方塊色彩的方式支援淡色及深色模式。

可重複使用的資產

另一種節省快閃記憶體的方法是限制資產總數。 這當然可透過採用非常簡單的設計加以達成,不過有時可重複使用相同資產多次,以限制資產的現有數量。

在快閃記憶體受限的電動自行車示範中,這種方法用於天氣螢幕。 天氣圖示是以相同資產縮放配合所有3種尺寸。 由於這是縮放調整的資產,因此SVG格式會比壓縮更為理想,即使RLE使用的快閃記憶體較少。 不過如果資產是以RLE格式儲存為所有3種尺寸,總計使用的快閃記憶體就會更多。

此外按鈕也是實作為可重複使用的資產。 例如按鈕會與其圖示分開,以便讓按鈕能夠重複使用。

示範中使用可重複性的另一種情況則是背景。 示範中共有5種不同的背景設計,不過使用可調整資產(方塊及可重複使用的資產)就可僅以一個資產和方塊建立所有背景。

提升效能

開發快閃記憶體受限的應用程式時,會有降低效能的風險。 不過如果有備用RAM可供使用,就有方式可以提升應用程式效能。 By using Dynamic Bitmaps and Cacheable Containers, it is possible to draw static snapshots of assets or containers to RAM. 之後無論何時使用資產或容器,就可改為使用快取版本的資產或容器。 快取版本只是RAM之中的點陣圖,亦即渲染時間與渲染一般點陣圖相同。

在快閃記憶體受限的電動自行車示範中,可快取容器用於捲動SVG資產及向量字型,同時維持良好效能。

將天氣元素作為可快取容器

一般來說,向量字型只要在執行階段移動或可移動,就會受到快取。 這樣可確保達到最低30 FPS,不受捲動的向量字型影響。

示範中使用的另一項秘訣,就是讓壓縮點陣圖解壓縮為點陣圖快取。 將點陣圖解壓縮至RAM,就能在可縮放及可旋轉的小工具中使用。 點陣圖解壓縮時,TouchGFX在參考點陣圖ID時一律使用解壓縮的快取版本。 以下是電動自行車示範之中的範例。 壓縮點陣圖只要進行解壓縮,之後點陣圖就能像一般點陣圖一樣使用。

StartView.cpp
StartView::StartView()
{
Bitmap::decompress(BITMAP_MAIN_RIPPLE_LEFT_ID); // Decompress compressed image to bitmap cache
Bitmap::decompress(BITMAP_MAIN_RIPPLE_RIGHT_ID); // Decompress compressed image to bitmap cache
}

void StartView::setupScreen()
{
leftMainRippleScale.setBitmap(BITMAP_MAIN_RIPPLE_LEFT_ID); // Set bitmap for Scalable Image
rightMainRippleScale.setBitmap(BITMAP_MAIN_RIPPLE_RIGHT_ID); // Set bitmap for Scalable Image
leftMainRippleScale.setWidthHeight(0, 0); // Set scale of image
rightMainRippleScale.setWidthHeight(0, 0); // Set scale of image
}

由於大量使用動態點陣圖,快閃記憶體受限的電動自行車示範需要的點陣圖快取為922 KB, 代表需要大量的備用RAM。 不過這項示範也讓快閃記憶體達到接近極限的節省幅度。 如果是更簡單的應用程式,或是不那麼重視效能需求的應用程式,就有可能大幅減少所需的點陣圖快取。

結論

本文介紹如何限制TouchGFX應用程式的快閃記憶體使用量。

這4種節省快閃記憶體的概念,可在所有STM32硬體平台使用,不過請記得SVG與向量字型具有昂貴的渲染成本。 因此如果沒有向量渲染硬體加速,或是沒有可用的額外運算能力,就可能造成效能下降。

快閃記憶體受限GUI開發的概念,可能會對效能造成不利影響,不過可使用動態點陣圖及可快取容器提升效能。

各項節省快閃記憶體的方法,可提供節省快閃記憶體的龐大潛能。 各種概念可確切節省的快閃記憶體容量,需視特定應用程式而定,不過對快閃記憶體受限的電動自行車示範而言,節省了92%的快閃記憶體。