Generator使用者指南
TouchGFX Generator是X-CUBE-TOUCHGFX的一部分,也是CubeMX附加軟體元件,可幫助開發人員配置TouchGFX讓應用可在開發者的硬體平台上執行。 根據現有的CubeMX設定與使用者的輸入,TouchGFX Generator將產生用以配置一個可運作的TouchGFX應用所需的所有檔案, 包含了TouchGFX HAL、TouchGFX OSAL和TouchGFX配置檔。
以CubeMX產生程式碼後,可透過用來開發UI的TouchGFX Designer來打開TouchGFX專案。 TouchGFX Designer會自動將所有額外產生的程式碼檔案加入CubeMX所指定的目標IDE當中。
啟用TouchGFX Generator
下圖可看到在附加軟體(Additional Software)分類(Categories)展開項目中TouchGFX Generator已被啟用的專案。 使用者可透過按「附加軟體(Additional Software)」按鈕來存取X-CUBE以新增功能。
下圖展示在專案中如何啟用TouchGFX Generator:
產生程式碼的架構
在描述TouchGFX Generator的功能之前,先了解所產生程式碼的架構以及開發人員如何使用該架構來客製化配置和行為至關重要。
要保護由CubeMX所產生的C程式碼中所加入的使用者程式碼,就必需將使用者程式碼置於「使用者程式碼(User Code)」程式碼區段當中。在TouchGFX Generator所產生的C++程式碼中,這樣的靈活性是透過物件繼承的方式來實現。
透過附加軟體(Additional Software)新增並啟用TouchGFX Generator之後,CubeMX會一直為專案建立一個TouchGFX資料夾。 無論配置如何,該資料夾總是包含相同的檔案成員,而檔案內容則因CubeMX和使用者配置而異。
由以下的清單可看到啟用TouchGFX Generator之後的CubeMX專案內容,並列出與TouchGFX相關較完整的檔案成員。 在清單之後的表格則列出了最重要項目的職責(responsibility)。
TouchGFX Folder
│ .mxproject
│ myproject.ioc
├───Core
├───Drivers
├───EWARM
├───Middlewares
└───TouchGFX
│ ApplicationTemplate.touchgfx.part
├───App
│ app_touchgfx.c
│ app_touchgfx.h
└───target
│ STM32TouchController.cpp
│ STM32TouchController.hpp
│ TouchGFXGPIO.cpp
│ TouchGFXHAL.cpp
│ TouchGFXHAL.hpp
│
└───generated
OSWrappers.cpp
TouchGFXConfiguration.cpp
TouchGFXGeneratedHAL.cpp
TouchGFXGeneratedHAL.hpp
資料夾 | 職責(Responsibility) |
---|---|
myproject.ioc | CubeMX專案檔 |
Core | main.c 與啟動程式碼(startup code) |
Drivers | CMSIS與MCU系列驅動程式 |
EWARM | IDE專案資料夾。 可以為EWARM,MDK-ARM或STM32CubeIDE |
Middlewares | 包含TouchGFX函式庫/標頭檔以及FreeRTOS等第三方軟體。 |
ApplicationTemplate.touchgfx.part | CubeMX使用與TouchGFX Designer專案相關的資訊(如螢幕尺寸和位元深度)來更新.part檔案 |
App | 為X-CUBE和CubeMX的介面。 app_touchgfx.c 包含了用於初始化TouchGFX並啟動其主迴圈的MX_TouchGFX_Process (void) 和MX_TouchGFX_Init (void) 二個函式的定義。 |
target/generated | 該子資料夾包含唯讀檔,當配置更改時,這些唯讀檔會被CubeMX所覆蓋。 TouchGFXGeneratedHAL.cpp 是TouchGFX的HAL 物件類別的子類別,包含了CubeMX根據目前的設定所產生的程式碼。 OSWrappers.cpp (OSAL)包含與TouchGFX引擎同步所需的函式。最後是TouchGFXConfiguration.cpp ,包含了用來建構和設定TouchGFX(包括HAL)的程式碼。 |
target | 包含大量的檔案,使用者可修改這些檔案以擴展HAL行為,或者修改檔案以覆蓋由CubeMX產生的配置。 STM32TouchController.cpp 包含了觸控控制器操作的空介面。 TouchGFXHAL.cpp 定義了TouchGFXGeneratedHAL 的物件子類別TouchGFXHAL 。 |
需要注意的是TouchGFXConfiguration.cpp
包含了一個用來建構HAL的函式, 以及一個用於啟動TouchGFX主迴圈的函式。 在可編輯的使用者類別TouchGFXHAL
當中可以新增附加的配置。 HAL的一般架構如下所示 :
特性概述
啟用TouchGFX Generator之後在使用者介面可看到三個設定項目群組:
- 相依關係(Dependencies) - 此設定項目群組用來通知開發人員包含配置中的相依關係、警告或具體錯誤的訊息。 若沒有條目則該項目群組將隱藏。
- 顯示(Display) - 此設定項目群組包含與顯示有關的配置如介面、影像緩衝區的位元深度、寬度和高度。 這些配置會直接影響TouchGFX專案裡畫布(canvas)的大小以及根據圖源資產(asset)所產生的程式碼。
- 驅動程式(Driver) - 此設定項目群組允許使用者選擇與應用相關的時標源(tick source)、圖形加速和RTOS有關的一些現成驅動程式。 由於CubeMX支援FreeRTOS(CMSIS RTOS v1與v2)的配置設定,TouchGFX Generator可為每個選項提供驅動程式。
顯示(Display)
顯示(Display)設定項目群組群組包含與顯示有關的配置,如介面、尺寸和緩衝區使用策略。
介面與尺寸
目前STM32微控制器可使用多種顯示介面,如:
- 並行式RGB
- MIPI DSI
- FMC
- SPI
對於帶有LTDC的MCU來說,TouchGFX Generator 可產生驅動程式來將影像緩衝區的內容傳輸到相連的顯示器。 而對於DSI、FMC和SPI介面來說,驅動程式必須由開發人員自行實作。
Further reading
緩衝區策略
可透過TouchGFX Generator設定以下影像緩衝區策略:
- 單一影像緩衝區 - 僅使用一個應用影像緩衝區。 性能可能會受限,但記憶體用量較少。 可與「緩衝區位置(Buffer Location)」的配置一起使用以將其放置在內部RAM當中。 若需更進一步的最佳化,使用者可以定義一個函式來回傳顯示控制器當前正在處理的「行(current line)」。 框架可使用該方法在該圖框當中對內容已被傳輸到顯示器的記憶體作更新。
- 雙影像緩衝區 - 使用兩個影像緩衝區。 通常是指以更大的記憶體用量為代價來換取更好的性能。
- 局部緩衝區 - 將一個或多個由使用者定義的記憶體區塊作為影像緩衝區。 此策略適用於不依賴外部RAM但所使用連接的顯示器其全部完整的影像緩衝區卻超過內部可用記憶體這類型低成本的方案。
對單一緩衝區與雙緩衝區來說,使用者可透過「緩衝器位置(Buffer Location)」來設定其記憶體位置,此設定提供以下選項:
- 依配置(By Allocation) - 允許連結器根據連結器設定檔來放置影像緩衝記憶體。 預設選項為置於內部RAM(internal RAM)中。
- 依位址(By Address) - 允許使用者定義一個(單)或兩個(雙)影像緩衝區位址。
局部緩衝區策略允許使用者定義以下參數:
- 區塊數量(始終放置在內部RAM中)
- 區塊大小(位元組數)
要了解有關局部緩衝策略的一些核心概念,請閱讀關於「使用局部影像緩衝區以降低記憶體用量」的專文 此專文從概念上說明了如何實現局部緩衝區,而要稍微留意的是在專文中所展示的程式碼會與TouchGFX Generator所產生的程式碼略有不同。 有關為這些策略而產生的具體程式碼範例,請參見影像緩衝策略。
驅動程式
這個驅動程式的設定項目群組讓開發人員可以為TouchGFX AL的各種功能選擇驅動程式。
應用時標源(Application Tick Source)
應用時標源定義了應用程式的運作進行方式。 開發人員有以下的選項:
- LTDC - 如果在「顯示(Display)」的設定項目群組當中將介面(Interface)設為「LTDC」,則應用時標源即可設定為「LTDC」。 這表示TouchGFX Generator將在
TouchGFXGeneratedHAL
物件類別當中置入驅動函式(LTDC中斷處理程式)並在此驅動函式當中透過呼叫OSWrappers::signalVSync()
來驅使應用程式的運作。 - 客製化 > - 在這種情況下,開發人員需要自行實作一個處理函式(handler)以便透過重複呼叫
OSWrappers::signalVSync()
來驅使應用程式的運作。
圖形加速器
關於圖形加速開發人員有三個選項:
- 無 - 應用程式僅使用CPU來繪製圖框(frames)。
- Chrom-ART (DMA2D) - 應用程式在可以使用Chrom-ART的情況下使用Chrom-ART來移動和混合像以釋放CPU資源。 驅動程式由TouchGFX Generator安裝因此開發人員不需要做任何處置。
TouchGFX Generator提供的Chrom-ART (DMA2D) 驅動程式支援兩種TransferCompleteInterrupt的處理方式:
- 使用STM32Cube HAL驅動程式,其中回呼函式(callback function)註冊到dma2d的控制代碼(handle)
hdma2d. XferCpltCallback
。 - 直接使用中斷處理程式
DMA2D_IRQHandler ()
。
在CubeMX藉由開啟或關閉DMA2D IP配置NVIC Setting分頁裡的DMA2D全域中斷,便可以在這兩種方式之間作切換。 開啟全域中斷可以產生選項1的程式碼,關閉全域中斷可以產生選項2的程式碼。
Note
即時作業系統
開發人員可在TouchGFX使用任何的RTOS(甚至不使用作業系統)。 如「抽象層架構(Abstration Layer Architecture)」中所述,依據使用者所選的RTOS,TouchGFX引擎使用OSWrappers
介面來同步TouchGFX引擎的主要事件迴圈和影像緩衝區之間的存取。
在CubeMX當中可以接設定FreeRTOS,而TouchGFX Generator讓使用者同時為「RTOS任務的定義」和「TouchGFX RTOS驅動程式 」產生程式碼。 TouchGFX Generator可產生相容CMSIS V1和CMSIS V2的RTOS驅動程式以相容任何的CMSIS RTOS。 在這種情況下,開發人員無法依賴CubeMX產生RTOS任務定義的程式碼而必須在使用者程式碼中完成。
下圖顯示了透過TouchGFX Generator可用的選項。
呼叫以下函式即進入TouchGFX主迴圈。
void MX_TouchGFX_Process(void);
開發者需要在執行TouchGFX任務的處理函式(task handler)當中呼叫此函式。 如果使用者在CubeMX配置了名為DefaultTask
的FeeRTOS任務,則可由以下範例看到如何在此任務處理程式的使用者程式區段(user code section)中藉由呼叫MX_TouchGFX_Process()
來啟動TouchGFX。
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
MX_TouchGFX_Process();
/* USER CODE END 5 */
}
啟用FreeRTOS之後CubeMX還會產生osKernelStart()
的呼叫以啟動排程器(scheduler)。
其他CMSIS相容的OS
當開發人員不使用CubeMX所提供的FreeRTOS而要採用其他CMSIS相容的即時作業系統時就必須自行手動完成RTOS配置和任務定義。 通常需要以下步驟:
- 設定RTOS
- 定義用來執行TouchGFX的任務(以便在其中呼叫
MX_TouchGFX_Process
) - 啟動排程器(scheduler)
以下是如何對Azure RTOS執行步驟2和3的範例。 由於CubeMX無法為此作任何配置,因此必須在產生的使用者程式碼區段(User Code Sections)中執行所有操作以避免自行新增的程式碼被覆蓋。 以下為GUI任務函式定義實作的虛擬程式碼(pseudo code)。 任何不是由CubeMX產生的程式碼通常都要分散置於main.c
程式檔當中的使用者程式碼區段(User Code Sections)。
/* BEGIN USER CODE SECTION */
#include "tx_api.h"
#define GUI_THREAD_STACK_SIZE 1024
TX_THREAD gui_thread;
void gui_thread_entry(ULONG thread_input); //Thread prototype
/* END USER CODE SECTION */
int main()
{
/* BEGIN USER CODE SECTION - Choose an appropriate one from main.c */
/* Allocate the stack for gui thread */
tx_byte_allocate(...);
/* Create the gui thread. */
tx_thread_create(&gui_thread, "GUI Thread", gui_thread_entry, 0,
pointer, GUI_TASK_STACK_SIZE,
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
/* END USER CODE SECTION*/
於任務處理函式當中呼叫MX_TouchGFX_Process
以啟動TouchGFX引擎主迴圈。
/* BEGIN USER CODE SECTION */
void gui_thread_entry(ULONG thread_input)
{
MX_TouchGFX_Process();
}
/* END USER CODE SECTION*/
啟動排程器以啟動GUI任務及TouchGFX應用。
/* BEGIN USER CODE SECTION */
tx_kernel_enter();
/* END USER CODE SECTION*/
額外功能
外部資料讀取器
對於RGB565影像緩衝像素格式,TouchGFX支援所謂的資料讀取器(Data Reader)介面,讓開發者能夠直接從非記憶體映射(non-memory-mapped)的序列式快閃記憶體(serial flash)讀取資料,而無需進行暫存(caching),當然這需要增加額外的緩衝儲存區。 有關如何實作DataReader以便由非記憶體映射(non-memory-mapped)的快閃記憶體當中獲取應用程式圖資(asset)的範例請參見Serial Flash文章。
資料讀取器(Data Reader)選項通常適用在如STM32G0這一類沒有足夠的記憶體用於額外緩衝區的低成本解決方案。 在啟用DMA2D之後便無法啟用這個選項。
將影像緩衝像素格式(Framebuffer Pixel Format)設為RGB565之後便可看到新增了附加功能(Additional Features)設定項群組。
開發人員可進行以下設定:
- 外部資料讀取器:以來啟用或關閉功能。 如果啟用,TouchGFX會直接透過所產生的介面獲取圖資(assets)。 如果功能關閉,則開發者需要將影像暫存(cache)到記憶體緩衝區中。
- 外部資料讀取器:建立兩個緩衝區以便將影像或文字混合到影像緩衝區當中。 預設值為一個螢幕寬度乘上4位元組以支援ARGB8888像素格式的全尺寸影像。
- 最小DMA傳輸量:設定啟動DMA傳輸所需的最小位元組。 如果請求的傳輸量少於最小位元組便不會用到DMA。
在啟用外部資料讀取器(External Data Reader)的情況下產生程式碼會建立如下的附加檔案以利直接從非記憶體映射(non-memory-mapped)的快閃記憶體中獲取圖資(asset)。
TouchGFX/target/generated/TouchGFXGeneratedDataReader.cpp
TouchGFX/target/generated/TouchGFXGeneratedDataReader.hpp
TouchGFX/target/TouchGFXDataReader.cpp
TouchGFX/target/TouchGFXDataReader.hpp
像往常一樣,TouchGFX Generator產生的程式碼TouchGFXGeneratedDataReader
為唯讀,使用者的修改應該要在TouchGFXDataReader
物件類別中進行。 而TouchGFXGeneratedDataReader
繼承自touchgfx::FlashDataReader
物件類別 。
TouchGFX Generator會修改以下檔案來配置TouchGFX HAL以使用DataReader
。
TouchGFX/target/generated/TouchGFXConfiguration.cpp
TouchGFX/target/generated/TouchGFXGeneratedHAL.cpp
TouchGFX/target/generated/TouchGFXGeneratedHAL.hpp
Note
8位元 LTDC顏色查找表(Look-up Table)
當LTDC設定為以L8的格式讀取影像緩衝區,並且TouchGFX以[ABRG2222](.. /.. /api/classes/classtouchgfx_1_1_l_c_d8bppa_b_g_r2222), [ARGB222](.. /.. /api/classes/classtouchgfx_1_1_l_c_d8bppa_r_g_b2222), [BGRA2222](.. /.. /api/classes/classtouchgfx_1_1_l_c_d8bppb_g_r_a2222), 或[RGBA2222](.. /.. /api/classes/classtouchgfx_1_1_l_c_d8bppr_g_b_a2222)的方式作渲染算圖時,TouchGFX Generator將提供CLUT,並在TouchGFXHAL::initialize()
期間將該CLUT載入到LTDC中。 有關LTDC和CLUT的用法,詳見STM32 MCU參考手冊。
產生的專案
使用CubeMX中的產生程式碼(Generate Code)按鈕產生程式碼時可產生以下IDE的TouchGFX專案檔:
- EWARM
- MDK-ARM
- STM32CubeIDE
藉由選取以下與專案產生相關的選項可以得到較佳的專案目錄結構:
- 應用結構:進階
- 關閉 Generate under root(僅適用於STM32CubeIDE)
藉由選取以下與專案產生相關的選項可以得到較佳的專案目錄結構:
- 應用結構:進階
- 關閉 Generate under root(僅適用於STM32CubeIDE)
- 應用資料夾包含用於初始化和啟動TouchGFX的程式碼。
- target資料夾包含產生的唯讀程式檔(置於generated/目錄中)和可修改的使用者物件類別檔(
STM32TouchController.cpp
,TouchGFXGPIO.cpp
和TouchGFXHAL.cpp
) - .part檔案,使用TouchGFX Designer來開啟以建立完整的TouchGFX專案(包括TouchFX的標頭檔和函式庫)。part檔案包含為了產生TouchGFX應用程式碼設計人員需使用的相關程式資訊(如像素格式與畫布尺寸)。
TouchGFX Designer專案
以下程式碼是在產生程式碼的架構(Generated Code Architecture)章節當中提及的.part
檔案內容的範例。 當TouchGFX Designer建立新檔案(如新螢幕與圖資)時,後置產生指令(post-generate command,如下所示 )會更新CubeMX中選擇的專案(如EWARM )。
{
"Application": {
"Name": "my_project",
"TouchGfxPath": "../Middlewares/ST/touchgfx",
"AvailableColorDepths": [ 16 ],
"AvailableLCDs":
{
"16": "LCD16bpp"
},
"AvailableResolutions" :
[
{
"Width": 320,
"Height": 240
}
],
"PostGenerateTargetCommand" : "touchgfx update_project --project-file=../my_project.ioc --platform=m7"
},
"Version": "4.13.0"
}
使用TouchGFX Designer開啟.part檔案時,開發人員可以選擇載入具體實際的UI或從空白範本開始。
按下TouchGFX Designer當中的產生代碼(Generate Code)之後可得到如下的TouchGFX資料夾結構。 由下圖可看到TouchGFX資料夾結構的具體範例,當中以高亮度強調了產生後的新檔案及資料夾。
TouchGFX將從CubeMX的.ioc檔當中偵測所選取的IDE(STM32CubeIDE,EWARM,MDK-ARM),並使用新生成的檔案(如用於螢幕定義、圖像和字型的圖資)來更新專案檔。
此時,開發人員可以交互使用CubeMX,TouchGFX Designer和工具鏈/IDE,其中:
- CubeMX可以更新IDE專案中的驅動程式
- CubeMX根據UI相關變更來更新TouchGFX .part檔案,而設計工具(designer)可同時立即取得這些變更
- CubeMX根據TouchGFX與平台相關的TouchGFX Generator配置來產生HAL程式碼(TouchGFX/target/generated/)。
- TouchGFX Designer使用產生的程式碼來更新專案。
修改所產生的行為
需要注意的是,HAL的物件類別階層結構讓使用者可以覆寫(override)CubeMX所產生的HAL配置或行為(behavior)。 在以下範例中,開發人員可以修改initialize
函式對TouchGFX作額外的配置,或修改TouchGFXGeneratedHAL
當中現有的配置集組。
TouchGFXHAL.cpp
void TouchGFXHAL::initialize()
{
// Calling parent implementation of initialize().
//
// To overwrite the generated implementation, omit call to parent function
// and implemented needed functionality here.
// Please note, HAL::initialize() must be called to initialize the framework.
TouchGFXGeneratedHAL::initialize();
//Overriding configurations
hal.lockDMAToFrontPorch(true);
hal.setFingerSize(4);
hal....
}
升級專案
TouchGFX Generator的相關參數儲存在CubeMX專案檔.ioc當中。 當發佈新版TouchGFX Generator時,舊版的參數可能與新版的參數不相容,此時便需要進行轉移(migration)。
CubeMX不支援X-CUBE版本之間的升級。而由於.touchgfx
檔案內PostGenerateTargetCommand
當中的指令(如下所示),因此在按下產生代碼時TouchGFX Designer會自動執行升級。
.touchgfx
"PostGenerateTargetCommand" : "touchgfx update_project --project-file=../upgrade.ioc --platform=m7"
這道指令將讀取.ioc
檔並更新參數以適應X-CUBE-TOUCHGFX目前的版本。 由以下範例可以看到如何透過手動執行X-CUBE-TOUCHGFX 4.14.0的腳本(script)指令對X-CUBE-TOUCHGFX 4.13.0所建立的.ioc檔案進行升級。
Upgrade example using STM32F746 DISCO Application Template from 4.13.0 to 4.14.0
$ touchgfx update_project --project-file=../STM32F746G_DISCO.ioc
TouchGFX Generator 4.13.0 found
Creating backup of ../STM32F746G_DISCO.ioc as ../backup_STM32F746G_DISCO.ioc
Performing upgrade 4.13.0 -> 4.14.0 ... OK
以CubeMX開啟升級過的專案時CubeMX會提示使用者要安裝.ioc檔所指定的X-CUBE-TOUCHGFX版本(若指定版本尚未安裝的情況下)。 點選立即下載(Download now)後將下載並安裝X-Cube-TouchGFX-4.14.0。
升級期間會保留TouchGFX Generator中的所有設定,.ioc檔的備份檔會以前置檔名backup_
的方式放成原始檔旁。