隨著越來(lái)越多用戶選擇i.MX RT系列芯片制作產(chǎn)品,產(chǎn)品的需求以及芯片的用法也越來(lái)越多。本文將介紹在i.MX RT平臺(tái)中,如何創(chuàng)建LVGL項(xiàng)目并將其運(yùn)行在內(nèi)部SRAM而非SDRAM上。本文檔包含4個(gè)部分:通過(guò)GUI Guider生成LVGL工程;LVGL工程的FlexRAM內(nèi)存配置;修改工程配置使得程序運(yùn)行;使用局部緩沖區(qū)節(jié)省SRAM空間。本文檔以IAR項(xiàng)目為例。
用GUI Guider生成VGL工程
GUI Guider是恩智浦推出的一款圖形用戶界面開(kāi)發(fā)工具,在往期的加油站文章中,也有關(guān)于它的介紹,在此就不多做描述。讀者可以參考相關(guān)的文檔資料進(jìn)行了解學(xué)習(xí)。GUI GUIDER
1.創(chuàng)建LVGL工程
打開(kāi)GUI Guider v1.9.1 GA,創(chuàng)建兩個(gè)GUI Guider項(xiàng)目:一個(gè)LVGL v9項(xiàng)目,使用基于MIMXRT1170-EVKB和Rasberry Pi LCD顯示屏的數(shù)字儀表盤(pán)模板。一個(gè)LVGL v8項(xiàng)目,使用基于MIMXRT1050-EVKB和RK043FN66HS LCD顯示屏的數(shù)字儀表盤(pán)模板。以下是LVGL版本選擇的屏幕截圖。
2.根據(jù)你的設(shè)備修改工程配置
對(duì)于第一個(gè)RT1170-EVKB項(xiàng)目,無(wú)需修改GUI Guider中的配置。對(duì)于RT1050-EVKB項(xiàng)目,需要使用片內(nèi)SRAM來(lái)保存幀緩沖區(qū)。在GUI Guider工具中,點(diǎn)擊菜單上的“Project”按鈕打開(kāi)設(shè)置頁(yè)面。窗口中可以看到一些項(xiàng)目設(shè)置。將“Frame Buffer Location”修改為SRAM,即可將緩沖區(qū)保存到內(nèi)部RAM中。
FlexRAM配置
FlexRAM是一種高度可配置且靈活的RAM存儲(chǔ)器陣列。該存儲(chǔ)器陣列包含多個(gè)存儲(chǔ)器組,每個(gè)存儲(chǔ)器組可獨(dú)立配置,以便由不同類型的接口訪問(wèn),例如I-TCM(指令緊密耦合存儲(chǔ)器)、D-TCM(數(shù)據(jù)緊密耦合存儲(chǔ)器)或AX(系統(tǒng))。存儲(chǔ)器組可以用作ITCM、DTCM或OCRAM存儲(chǔ)器。本文檔將簡(jiǎn)要介紹RT1170和RT10XX系列的FlexRAM靜態(tài)配置以及運(yùn)行時(shí)配置。更改IOMUX_GPR_GPR17(在RT1170上,也包括IOMUX_GPR_GPR18)寄存器中定義的FLEXRAM_BANK_CFG字段的值。在設(shè)置IOMUX_GPR_GPR17/18的值之前,需要將IOMUXC_GPR_GPR16寄存器的FLEXRAM_BANK_CFG_SEL值設(shè)置為1,以啟用FlexRAM配置。設(shè)置FLEXRAM_BANK_CFG值來(lái)配置RAM類型:
?00:RAM組n未使用
?01:RAM組n為OCRAM
?10:RAM組n為DTCM
?11:RAM組n為ITCM
1.i.MX RT芯片F(xiàn)lexRAM配置
不同的i.MX RT芯片具有不同的內(nèi)存容量,因此每個(gè)芯片可配置的FlexRAM大小也不同。下表列出了不同i.MX RT芯片的FlexRAM信息。
對(duì)于i.MX RT1170,系統(tǒng)內(nèi)存映射如下所示。i.MX RT1170 SRAM的默認(rèn)配置如下表所示:
ITCM | DTCM | OCRAM |
256KB | 256KB | 1.5MB |
2.FlexRAM靜態(tài)配置
芯片通過(guò)POR上電后,i.MX RT會(huì)從eFuse中檢查FlexRAM組的值,以確定FlexRAM的分配。
OCRAM的最小配置為64KB。這是因?yàn)?a href="http://m.xsypw.cn/tags/rom/" target="_blank">ROM代碼的執(zhí)行至少需要64 KB的RAM。OCRAM的最小配置要求可能因設(shè)備而異。
本文檔不使用靜態(tài)配置方法,因此這里不再詳細(xì)介紹靜態(tài)配置。
3.FlexRAM動(dòng)態(tài)配置
FlexRAM也可以通過(guò)在運(yùn)行時(shí)更改IOMUXC_GPR寄存器的值來(lái)配置。首先,將IOMUXC_GPR_GPR16寄存器中定義的FLEXRAM_BANK_CFG_SEL位置1。然后,可以通過(guò)IOMUXC_GPR_GPR17(在RT1170上,還有IOMUXC_GPR_GPR18)寄存器中FLEXRAM_BANK_CFG的值來(lái)配置FlexRAM的大小。運(yùn)行時(shí)配置比靜態(tài)配置有兩個(gè)優(yōu)勢(shì):在靜態(tài)配置中,eFUse只能燒寫(xiě)一次,而FlexRAM配置無(wú)法多次調(diào)整;eFuse中只有4/6位配置位,不會(huì)窮盡所有FlexRAM Bank組合。
3.1確定FlexRAM的分配
首先,通過(guò)IOMUXC_GPR17(以及RT1170中的IOMUXC_GPR18)寄存器的FLEXRAM_BANK_CFG位,可以自由指定每個(gè)Bank的最終形態(tài)(ITCM/DTCM/OCRAM)。以下是FLEXRAM_BANK_CFG(i.MX RT1170芯片)的說(shuō)明。
FlexRAM bank configuration GPR17 of RT1170
FlexRAM bank configuration GPR18 of RT1170
3.2使能動(dòng)態(tài)配置
分配好FlexRAM Bank后,將IOMUXC_GPR16寄存器中的FLEXRAM_BANK_CFG_SET設(shè)置為1,F(xiàn)LEXRAM_BANK_CFG指定的配置就會(huì)立即生效。
FlexRAM bank configuration GPR16 of RT1170
在片內(nèi)RAM中運(yùn)行LVGL工程
現(xiàn)在基于MIMXRT1170-EVKB創(chuàng)建了LVGL工程(2個(gè)全尺寸幀緩沖區(qū)),并介紹了配置FlexRAM的方法,下面是使項(xiàng)目在內(nèi)部RAM而非外部SDRAM上運(yùn)行的步驟。
1.在startup文件中配置FlexRAM
本工程中,所有內(nèi)部RAM均配置為OCRAM,D-TCM和 I-TCM的大小均設(shè)置為0。此存儲(chǔ)設(shè)置僅用于演示如何將所有程序都放入內(nèi)部RAM,速度可能并非最快。打開(kāi)“startup_MIMXRT1176_cm7.s”,并在“SystemInit”之前添加配置代碼。參見(jiàn)以下代碼:
Reset_Handler CPSID I ;Maskinterrupts LDR R0, =0xE000ED08 LDR R1, =__vector_table STR R1, [R0] LDR R2, [R1] MSR MSP,R2 /*FlexRam Configuration*///OCRAM = 512KB, DTCM = 0KB ,ITCM = 0KB, ldr R0,=0x400E4040//gpr16 Enable FLEXRAM_BANK_CFG ldr R1,=0x0000AA07 str R1,[R0] ldr R0,=0x400E4044//gpr17 0:15 ldr R1,=0x00005555 str R1,[R0] ldr R0,=0x400E4048//gpr18 0:15 ldr R1,=0x00005555 str R1,[R0] LDR R0, =SystemInit BLX R0 CPSIE I ;Unmaskinterrupts LDR R0, =__iar_program_start BX R0
現(xiàn)在OCRAM大小設(shè)置為2MB。保存更改,F(xiàn)lexRAM配置將在項(xiàng)目運(yùn)行時(shí)生效。
2.修改鏈接文件
GUI Guider生成的基于i.MX RT芯片的LVGL工程默認(rèn)存儲(chǔ)在Nor Flash和SDRAM中。在工程選項(xiàng)中打開(kāi)Linker File,刪除其他data region,只保留1個(gè)data region。將整個(gè)OCRAM設(shè)置為data region。只保留data region配置,刪除其他配置。參見(jiàn)以下代碼:
/* define symbol m_interrupts_ram_start = 0x20200000; define symbol m_interrupts_ram_end = 0x20200000 + __ram_vector_table_offset__; define symbol m_data_start = m_interrupts_ram_start + __ram_vector_table_size__; define symbol m_data_end = 0x203FFFFF; */ definesymbolm_data_start =0x20240000; definesymbolm_data_end =0x203EFFFF; definesymbolm_ncache_start =0x203F0000; definesymbolm_ncache_end =0x203FFFFF; … define exportedsymbol__VECTOR_TABLE = m_interrupts_start; //define exported symbol __VECTOR_RAM = isdefinedsymbol(__ram_vector_table__) ? m_interrupts_ram_start : m_interrupts_start; define exportedsymbol__VECTOR_RAM = m_interrupts_start; define exportedsymbol__RAM_VECTOR_TABLE_SIZE =0x0; define memory memwithsize = 4G; define region TEXT_region =mem:[fromm_interrupts_start to m_interrupts_end] |mem:[fromm_text_start to m_text_end]; define region DATA_region =mem:[fromm_data_start to m_data_end-__size_cstack__]; define region CSTACK_region =mem:[fromm_data_end-__size_cstack__+1to m_data_end]; define region NCACHE_region =mem:[fromm_ncache_start to m_ncache_end]; …3. 減小代碼尺寸
在GUI Guider生成的項(xiàng)目中,LVGL內(nèi)存大小默認(rèn)設(shè)置為2MB。通常項(xiàng)目不需要這么大的內(nèi)存。因此,此處將LV_MEM_SIZE改為80kB,以節(jié)省SRAM。
/*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/
#defineLV_MEM_SIZE (80U * 1024U)
4.編譯運(yùn)行工程
保存更改并構(gòu)建項(xiàng)目,查看“l(fā)vgl_guider_cm7.map”文件。內(nèi)存占用大小顯示在底部。
203'063 bytes of readonlycode memory
7'351'345 bytes of readonlydata memory
1'753'889 bytes of readwrite data memory
將其下載到開(kāi)發(fā)板,工程將成功運(yùn)行。
局部緩沖區(qū)刷新
另一個(gè)基于MIMXRT1050-EVKB的LVGL v8項(xiàng)目使用局部緩沖區(qū)刷新來(lái)節(jié)省SRAM空間。將緩沖區(qū)位置配置到SRAM中,生成的項(xiàng)目將在內(nèi)部SRAM而非外部SDRAM上運(yùn)行。
在“l(fā)vgl_support.c”文件中,如果啟用宏“FB_USE_SRAM”,則會(huì)創(chuàng)建兩個(gè)不同大小的幀緩沖區(qū):一個(gè)全尺寸緩沖區(qū)和一個(gè)部分尺寸緩沖區(qū)。
#ifFB_USE_SRAM #defineDRAW_BUF_HEIGHT (LCD_HEIGHT / 5) #defineDEMO_DB_SIZE LCD_WIDTH * DRAW_BUF_HEIGHT * LCD_FB_BYTE_PER_PIXEL SDK_ALIGN(__attribute__((section("FrameBuffer")))staticuint8_ts_frameBuffer[1][DEMO_FB_SIZE], DEMO_FB_ALIGN); SDK_ALIGN(__attribute__((section("DrawBuffer")))staticuint8_ts_lvglBuffer[DEMO_DB_SIZE], DEMO_FB_ALIGN); #else SDK_ALIGN(staticuint8_ts_frameBuffer[2][DEMO_FB_SIZE], DEMO_FB_ALIGN); #endif
緩沖區(qū)初始化也不一樣。
#ifFB_USE_SRAM lv_disp_draw_buf_init(&disp_buf, s_lvglBuffer,NULL, LCD_WIDTH * DRAW_BUF_HEIGHT); #else lv_disp_draw_buf_init(&disp_buf, s_frameBuffer[0], s_frameBuffer[1], LCD_WIDTH * LCD_HEIGHT); #endif … /* Partial refresh */ #ifFB_USE_SRAM disp_drv.full_refresh =0; #else disp_drv.full_refresh =1; #endif
Flush方式是更新改變的區(qū)域。
#ifFB_USE_SRAM staticvoidDEMO_WaitVsync(lv_disp_drv_t*disp_drv) { s_framePending =true; #ifdefined(SDK_OS_FREE_RTOS) if(xSemaphoreTake(s_frameSema, portMAX_DELAY) != pdTRUE) { PRINTF("Display flush failed "); assert(0); } #else while(s_framePending) { } #endif } staticvoidcopy_area(constlv_area_t*area,lv_color_t*color_p,uint8_t*fb,uint32_tfbStrideBytes) { uint32_ty; uint32_tareaWidth =lv_area_get_width(area); fb += (area->y1 * fbStrideBytes + area->x1 *sizeof(lv_color_t)); for(y = area->y1; y <= area->y2; y++) { lv_memcpy(fb, color_p, areaWidth *sizeof(lv_color_t)); fb += fbStrideBytes; color_p += areaWidth; } } staticvoidDEMO_FlushDisplay(lv_disp_drv_t*disp_drv,constlv_area_t*area,lv_color_t*color_p) { /* Wait VSYNC for each small update. */ DEMO_WaitVsync(disp_drv); /* Copy data from draw buffer to frame buffer. */ copy_area(area, color_p, (uint8_t*) s_frameBuffer, LCD_WIDTH * LCD_FB_BYTE_PER_PIXEL); SCB_CleanInvalidateDCache(); lv_disp_flush_ready(disp_drv); } #else staticvoidDEMO_FlushDisplay(lv_disp_drv_t*disp_drv,constlv_area_t*area,lv_color_t*color_p) { DCACHE_CleanInvalidateByRange((uint32_t)color_p, DEMO_FB_SIZE); ELCDIF_SetNextBufferAddr(LCDIF, (uint32_t)color_p); s_framePending =true; #ifdefined(SDK_OS_FREE_RTOS) if(xSemaphoreTake(s_frameSema, portMAX_DELAY) == pdTRUE) { /* IMPORTANT!!! * Inform the graphics library that you are ready with the flushing*/ lv_disp_flush_ready(disp_drv); } else { PRINTF("Display flush failed "); assert(0); } #else while(s_framePending) { } /* IMPORTANT!!! * Inform the graphics library that you are ready with the flushing*/ lv_disp_flush_ready(disp_drv); #endif } #endif
通過(guò)修改鏈接器文件,我們可以將“DrawBuffer”和“FrameBuffer”放入SRAM中,這些緩沖區(qū)的大小將遠(yuǎn)小于兩個(gè)全尺寸緩沖區(qū)。因此,LVGL項(xiàng)目可以在內(nèi)部RAM上運(yùn)行。
小結(jié)
本文介紹了如何使基于i.MX RT芯片的LVGL工程在內(nèi)部RAM上運(yùn)行而不是外部SDRAM。一種方法是使用FlexRAM擴(kuò)展OCRAM的大小,以便獲得連續(xù)的RAM來(lái)存儲(chǔ)緩沖區(qū)。另一種方法是使用部分緩沖區(qū)而不是全尺寸緩沖區(qū),這樣可以節(jié)省SRAM。
-
芯片
+關(guān)注
關(guān)注
459文章
52378瀏覽量
439029 -
SDRAM
+關(guān)注
關(guān)注
7文章
442瀏覽量
56201 -
恩智浦
+關(guān)注
關(guān)注
14文章
5964瀏覽量
115125 -
sram
+關(guān)注
關(guān)注
6文章
784瀏覽量
115807 -
LVGL
+關(guān)注
關(guān)注
1文章
104瀏覽量
3629
原文標(biāo)題:在i.MX RT片內(nèi)RAM中運(yùn)行LVGL工程
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
恩智浦i.MX RTxxx系列MCU的特性
i.MX RT1050平臺(tái)的相關(guān)資料推薦
恩智浦最新的應(yīng)用處理器 i.MX 95采用專有NPU IP進(jìn)行片上AI加速
01:i.MX RT的市場(chǎng)應(yīng)用和參考解決方案

恩智浦i.MX RT1170開(kāi)創(chuàng)GHz MCU時(shí)代
恩智浦i.MX RT1170在將該系列帶上了更高的層面
恩智浦發(fā)布新一代i.MX 9系列應(yīng)用處理器
恩智浦推出核跨界MCU的第二款產(chǎn)品i.MX RT1160
痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU特性那些事(1)- 概覽

i.MX RT開(kāi)發(fā)筆記-08 | i.MX RT1062嵌套中斷向量控制器NVIC(按鍵中斷檢測(cè))

基于i.MX RT單芯片實(shí)現(xiàn)的GUI圖形顯示和語(yǔ)音控制解決方案
適用于i.MX RT500和i.MX RT600 MCU的Xtensa音頻框架介紹
恩智浦i.MX RT1060/1010上串行NOR Flash冗余程序啟動(dòng)設(shè)計(jì)

恩智浦i.MX RT1170 uSDHC eMMC啟動(dòng)時(shí)間

評(píng)論