一、引言
眾所周知,i.MX RT系列是MCU中的性能強者,超高的主頻、豐富的外設(shè)以及足夠大的存儲使其能輕松應(yīng)用于各類領(lǐng)域。其中,在圖像視頻方面,i.MX RT1050及以上系列,集成了PXP圖形加速器,可用于對LCD顯示之前的圖像進(jìn)行處理。
i.MX RT1170更是集成了支持OpenVG的GPU2D模塊,可用于矢量繪圖等操作,還集成了兩類LCD控制器eLCDIF和LCDIFv2,并且在物理接口方面增加了MIPI DSI的支持。
不過強大的硬件支持不是今天文章的重點,今天來玩點“軟”的。
去年,Arm在其Github上發(fā)布了一個針對全體Cortex-M處理器的2D圖形加速庫——Arm-2D(暫定名)。在其Github倉庫的文檔中可以看出,Arm-2D致力于打造一層抽象層,為芯片供應(yīng)廠商提供的硬件以及GUI廠商提供的圖形圖形庫之間的接口設(shè)立一層驅(qū)動標(biāo)準(zhǔn)。并且Arm-2D也提供了一系列的2D圖形加速API。
本文以移植Arm-2D到i.MX RT1050-EVKB并繪制一些圖形界面為例,動手部署。
二、準(zhǔn)備工作
1. 工程下載
首先,我們需要獲取Arm-2D庫,打開其官方github倉庫:https://github.com/ARM-software/EndpointAI,可以看到有四個branch可以選擇,此處選擇developing分支(用于開發(fā)的分支,更新相對頻繁)。下載到本地后,將Arm-2D目錄(EndpointAI-main-arm-2d-developingKernelsResearchArm-2D)拷貝到我們的目標(biāo)工程目錄下,這里我們選擇i.MX RT1050的SDK中elcdif_rgb工程,以IAR工程為例。打開IAR工程,將”Arm-2D”下的”Helper”和”Library”全部文件添加到工程中。
2. 環(huán)境配置
將”Arm-2D/Library/Include”和”Arm-2D/Helper/Include”添加到Include搜索路徑列表里,接著開始配置工程所需的選項。
在Arm-2D的官方介紹中,我們知道其依賴于CMSIS,并且需要CMSIS 5.7.0及以上的版本。
打開IAR的安裝位置,轉(zhuǎn)到armCMSIS位置下,點開readme_patch.txt查看是否是5.7.0及以上版本。若你的CMSIS版本為5.7.0以下,請下載新版本,以替換原CMSIS文件。
確定了足夠高的版本后,在工程配置中的”General Options-Library Configuration”中勾選上”USECMSIS”和”DSP Library”。
3.關(guān)鍵函數(shù)
Arm-2D只負(fù)責(zé)軟件層面的圖形操作,而硬件部分則需要我們自己實現(xiàn),所以此處我們選用SDK中,已經(jīng)實現(xiàn)好LCD初始化的elcdif_rgb工程進(jìn)行部署。
我們所需要做的是,提供一個向LCD指定區(qū)域傳送位圖的函數(shù)。而i.MX RT1050自帶LCD控制器,則更方便實現(xiàn)所需的操作。
所需傳送位圖的函數(shù)如下:
/* i.MX RT1050-EVK */
#define GLCD_WIDTH 480
#define GLCD_HEIGHT 272
#define LCD_BASE_ADDR 0x81E00000 //m_ncache_start
#define frame_buf ((volatile uint16_t *)LCD_BASE_ADDR)
int32_t GLCD_DrawBitmap (uint32_t x, uint32_t y, uint32_t width, uint32_t height, const uint8_t *bitmap)
{
volatile uint16_t *phwDes = frame_buf + y * GLCD_WIDTH + x;
const uint16_t *phwSrc = (const uint16_t *)bitmap;
for (int_fast16_t i = 0; i < height; i++) {
memcpy ((uint16_t *)phwDes, phwSrc, width * 2);
phwSrc += width;
phwDes += GLCD_WIDTH;
}
return 0;
}
以上可以直接用存儲器讀寫操作將需要傳送的位圖傳到LCD指定位置,其中顯示緩存的基地址是linker文件中的m_ncache_start。
參數(shù)‘x’和’y’描述需要在LCD中顯示的起始位置;參數(shù)’width’和’height’描述所傳位圖的尺寸;而參數(shù)’bitmap’則代表位圖數(shù)據(jù)。
三、圖形繪制
1. 畫第一個方塊
接下來嘗試?yán)肁rm-2D進(jìn)行圖形繪制了。
首先,原工程中保留硬件配置以及外設(shè)初始化的部分,將frameBuffer的操作去除。
接著,在需要用到Arm-2D的地方包含頭文件”arm_2d.h”,并在主函數(shù)中進(jìn)行初始化,調(diào)用”arm_2d_init();”。此處,我們需要用到Arm-2D的PFB(partial framebuffer),在需要用到PFB Helper的地方包含”arm-2d_helper.h”,建立一個PFB對象并利用其進(jìn)行我們所需圖像的構(gòu)建。
以下為PFB的初始化代碼:
static arm_2d_helper_pfb_t s_tExamplePFB;
//! initialise FPB helper
if (ARM_2D_HELPER_PFB_INIT(
&s_tExamplePFB, //!< FPB Helper object
APP_IMG_WIDTH, //!< screen width
APP_IMG_HEIGHT, //!< screen height
uint16_t, //!< color date type
PFB_BLOCK_WIDTH, //!< PFB block width
PFB_BLOCK_HEIGHT, //!< PFB block height
1, //!< number of PFB in the PFB pool
{
.evtOnLowLevelRendering = {
//! callback for low level rendering
.fnHandler = &__pfb_render_handler,
},
.evtOnDrawing = {
//! callback for drawing GUI
.fnHandler = &__pfb_draw_handler,
},
}
) < 0) {
//! error detected
assert(false);
}
在此函數(shù)中,可以設(shè)置在屏中顯示的大小、像素的數(shù)據(jù)類型、PFB的規(guī)格以及PFB的數(shù)量,并設(shè)置底層渲染函數(shù)” __pfb_render_handler”以及圖形繪制函數(shù)”__pfb_draw_handler”。
底層渲染函數(shù)” pfb_render_handler”用來將PFB中處理好的圖像數(shù)據(jù)渲染到屏幕的指定位置進(jìn)行顯示:
static IMPL_PFB_ON_LOW_LV_RENDERING(__pfb_render_handler)
{
const arm_2d_tile_t *ptTile = &(ptPFB->tTile);
ARM_2D_UNUSED(pTarget);
ARM_2D_UNUSED(bIsNewFrame);
GLCD_DrawBitmap(ptTile->tRegion.tLocation.iX,
ptTile->tRegion.tLocation.iY,
ptTile->tRegion.tSize.iWidth,
ptTile->tRegion.tSize.iHeight,
ptTile->pchBuffer);
arm_2d_helper_pfb_report_rendering_complete(&s_tExamplePFB,
(arm_2d_pfb_t *)ptPFB);
}
而圖形繪制函數(shù)”__pfb_draw_handler”則是利用Arm-2D庫里的各類API進(jìn)行圖形的繪制。下面就在此函數(shù)中簡單繪制一個圖形以演示:
static IMPL_PFB_ON_DRAW(__pfb_draw_handler)
{
ARM_2D_UNUSED(pTarget);
ARM_2D_UNUSED(bIsNewFrame);
arm_2d_region_t tBox = {
.tLocation = {50,50}, //設(shè)定目標(biāo)坐標(biāo)
.tSize = {200, 100}, //設(shè)定目標(biāo)大小
};
//! 利用此函數(shù)向整個PFB填充白色
arm_2d_rgb16_fill_colour(ptTile, NULL, 0xFFFF);
//! 向指定box區(qū)域填充黑色
arm_2d_rgb16_fill_colour(ptTile, &tBox, 0x0000);
//! 更改box的坐標(biāo),大小不變
tBox.tLocation.iX -= 10;
tBox.tLocation.iY -= 10;
//! 向修改后的box指定區(qū)域填充藍(lán)色,并且使用 50%(128/255)的透明效果
arm_2d_rgb565_fill_colour_with_alpha(
ptTile,
&tBox,
(arm_2d_color_rgb565_t){0x001F}, //填充藍(lán)色
128); //!< 透明度
return arm_fsm_rt_cpl;
}
以上就繪制了如下圖的一個簡單圖標(biāo):
這里是利用”arm_2d_rgb16_fill_colour”和” arm_2d_rgb565_fill_colour_with_alpha”兩個API進(jìn)行矩形的繪制,可以看出這是16位RGB格式的色彩填充,當(dāng)然庫中也提供了32位RGB格式以及8位圖的繪制函數(shù);庫中還提供”arm_2dp_rgb16_draw_point”的畫點函數(shù)和”arm_2dp_rgb16_draw_pattern”的畫圖函數(shù)。當(dāng)然,想做一個圖形驅(qū)動標(biāo)準(zhǔn),肯定不止有draw這么基礎(chǔ)的能力,Alpha blending,Rotation等一系列圖形處理的功能都需要支持。
2. 做一個表盤界面
現(xiàn)在,將各項功能綜合運用起來,做一個圖形界面試試。
首先,掏出我們“祖?zhèn)鳌盠OGO,將其轉(zhuǎn)化為特定格式的數(shù)組,用的是Arm-2D庫中提供的工具,具體位置為”EndpointAIKernelsResearchArm-2D ools”,用法也在其中,考慮到1050-EVK所用的屏幕為480*272,此處將logo圖壓縮成512*280(比屏幕大,可做出背景移動的效果):”python img2c.py -i .logo.jpg --dim 512 280 --name logo”。
將生成的logo.c文件放到工程中。
除了背景,其余的表盤以及指針等圖像文件我們就用Arm-2D提供的例程里的。
在工程欄中新建”asset”分組,將” ..Arm-2Dexamplescommonasset”中除了”background.c”之外的c文件都選進(jìn)去,并將之前生成的”logo.c”文件也加入其中,以logo圖作為本次的背景。這一步是將所需的貼圖都加進(jìn)去。
接著,按照”watch_panel”的工程布局將需要的文件添加:”example_gui.c”和”example_gui.h”,并且依據(jù)工程修改主函數(shù)、補齊相關(guān)的配置。
- 程序運行時,先進(jìn)行相關(guān)的硬件配置及初始化操作,再進(jìn)行Arm-2D的初始化” arm_2d_init()”,到這里都和上一節(jié)畫一個矩形是一樣的;
- 接著,我們需要對繪制界面中刷新層進(jìn)行初始化“example_gui_init()”,函數(shù)定義在“example_gui.c”中;
- 進(jìn)行PFB的配置,與上節(jié)不同的是,將” pfb_draw_handler”改成“pfb_draw_background_handler”,而” pfb_draw_handler”需要留到后面進(jìn)行圖形繪制用;
- 在PFB配置完成后,調(diào)用PFB任務(wù)“arm_2d_helper_pfb_task(&s_tExamplePFB,NULL)”,其中第二個參數(shù)為所需刷新的臟矩陣(DirtyRegions)區(qū)域,“NULL”則表示需要全屏刷新;
- 調(diào)用圖形繪制函數(shù)“ARM_2D_HELPER_PFB_UPDATE_ON_DRAW_HANDLER(&s_tExamplePFB, &__pfb_draw_handler);”,其中繪制的部分都在“draw_handler”中的” example_gui_refresh”函數(shù)中,對之前添加進(jìn)工程的貼圖進(jìn)行各種操作就在這里進(jìn)行,具體可見“example_gui.c”;
- 最后,通過“while(1)”使程序運行在“display_task”中,對顯示屏指定區(qū)域的刷新、圖像的一些更新都在此實現(xiàn)。
經(jīng)過以上的一通操作之后,效果如下動圖所示:
從上可以看出,此工程中用了bit blit, alpha blending, rotation等效果:
- logo滾動背景利用一定范圍內(nèi)不斷變換坐標(biāo)的貼圖來實現(xiàn);
- 表盤利用”arm_2d_rgb565_alpha_blending_with_colour_masking”確定指定的透明度顏色蒙版來實現(xiàn);
- 兩個旋轉(zhuǎn)齒輪以及一根旋轉(zhuǎn)表針,通過” arm_2dp_rgb565_tile_rotation_with_alpha”區(qū)分透明度以及確定旋轉(zhuǎn)中心來分別實現(xiàn)。
四、總結(jié)
至此,基本的Arm-2D圖形繪制功能在i.MX RT1050-EVK上的實現(xiàn)就介紹完了。
本文只是簡單移植一個包含Arm-2D繪圖庫實現(xiàn)某些動畫效果的例子,已經(jīng)可以看到其多樣的功能,至于更多的一些效果,留給我們的想象空間還很足......
本文只是開篇,后續(xù),還會有對于Arm-2D在i.MX RT上更多的應(yīng)用介紹。
原文標(biāo)題:在i.MX RT10XX平臺上部署Arm-2D
文章出處:【微信公眾號:恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
mcu
+關(guān)注
關(guān)注
146文章
17123瀏覽量
350975 -
ARM
+關(guān)注
關(guān)注
134文章
9084瀏覽量
367378 -
移植
+關(guān)注
關(guān)注
1文章
379瀏覽量
28124 -
圖形界面
+關(guān)注
關(guān)注
0文章
37瀏覽量
7368
原文標(biāo)題:在i.MX RT10XX平臺上部署Arm-2D
文章出處:【微信號:NXP_SMART_HARDWARE,微信公眾號:恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論