0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

移植Arm-2D到i.MX RT1050-EVKB并绘制图形界面

痞子衡嵌入式 来源:恩智浦MCU加油站 作者:恩智浦MCU加油站 2022-07-12 10:05 次阅读

一、引言

众所周知,i.MX RT系列是MCU中的性能强者,超高的主频、丰富的外设以及足够大的存储使其能轻松应用于各类领域。其中,在图像视频方面,i.MX RT1050及以上系列,集成了PXP图形加速器,可用于对LCD显示之前的图像进行处理。

i.MX RT1170更是集成了支持OpenVG的GPU2D模块,可用于矢量绘图等操作,还集成了两类LCD控制器eLCDIF和LCDIFv2,并且在物理接口方面增加了MIPI DSI的支持。

不过强大的硬件支持不是今天文章的重点,今天来玩点“软”的。

去年,Arm在其Github上发布了一个针对全体Cortex-M处理器的2D图形加速库——Arm-2D(暂定名)。在其Github仓库的文档中可以看出,Arm-2D致力于打造一层抽象层,为芯片供应厂商提供的硬件以及GUI厂商提供的图形图形库之间的接口设立一层驱动标准。并且Arm-2D也提供了一系列的2D图形加速API。

本文以移植Arm-2D到i.MX RT1050-EVKB并绘制一些图形界面为例,动手部署。

二、准备工作

1. 工程下载

首先,我们需要获取Arm-2D库,打开其官方github仓库:https://github.com/ARM-software/EndpointAI,可以看到有四个branch可以选择,此处选择developing分支(用于开发的分支,更新相对频繁)。

下载到本地后,将Arm-2D目录(EndpointAI-main-arm-2d-developingKernelsResearchArm-2D)拷贝到我们的目标工程目录下,这里我们选择i.MX RT1050的SDK中elcdif_rgb工程,以IAR工程为例。打开IAR工程,将”Arm-2D”下的”Helper”和”Library”全部文件添加到工程中。

42fb6578-011c-11ed-ba43-dac502259ad0.png

2. 环境配置

将”Arm-2D/Library/Include”和”Arm-2D/Helper/Include”添加到Include搜索路径列表里,接着开始配置工程所需的选项。

在Arm-2D的官方介绍中,我们知道其依赖于CMSIS,并且需要CMSIS 5.7.0及以上的版本。

打开IAR的安装位置,转到armCMSIS位置下,点开readme_patch.txt查看是否是5.7.0及以上版本。若你的CMSIS版本为5.7.0以下,请下载新版本,以替换原CMSIS文件。

确定了足够高的版本后,在工程配置中的”General Options-Library Configuration”中勾选上”USECMSIS”和”DSP Library”。

4310f8fc-011c-11ed-ba43-dac502259ad0.png

3.关键函数

Arm-2D只负责软件层面的图形操作,而硬件部分则需要我们自己实现,所以此处我们选用SDK中,已经实现好LCD初始化的elcdif_rgb工程进行部署。

我们所需要做的是,提供一个向LCD指定区域传送位图的函数。而i.MX RT1050自带LCD控制器,则更方便实现所需的操作。

所需传送位图的函数如下:

/* 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。

参数‘x’和’y’描述需要在LCD中显示的起始位置;参数’width’和’height’描述所传位图的尺寸;而参数’bitmap’则代表位图数据。

三、图形绘制

1. 画第一个方块

接下来尝试利用Arm-2D进行图形绘制了。

首先,原工程中保留硬件配置以及外设初始化的部分,将frameBuffer的操作去除。

接着,在需要用到Arm-2D的地方包含头文件”arm_2d.h”,并在主函数中进行初始化,调用”arm_2d_init();”。此处,我们需要用到Arm-2D的PFB(partial framebuffer),在需要用到PFB Helper的地方包含”arm-2d_helper.h”,建立一个PFB对象并利用其进行我们所需图像的构建。

以下为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);
    }

在此函数中,可以设置在屏中显示的大小、像素的数据类型、PFB的规格以及PFB的数量,并设置底层渲染函数” __pfb_render_handler”以及图形绘制函数”__pfb_draw_handler”。

底层渲染函数” pfb_render_handler”用来将PFB中处理好的图像数据渲染到屏幕的指定位置进行显示:

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);
}

而图形绘制函数”__pfb_draw_handler”则是利用Arm-2D库里的各类API进行图形的绘制。下面就在此函数中简单绘制一个图形以演示:

static IMPL_PFB_ON_DRAW(__pfb_draw_handler)
{
    ARM_2D_UNUSED(pTarget);
    ARM_2D_UNUSED(bIsNewFrame);

    arm_2d_region_t tBox = {
        .tLocation = {50,50},    //设定目标坐标
        .tSize = {200, 100},     //设定目标大小
    };
    //! 利用此函数向整个PFB填充白色
    arm_2d_rgb16_fill_colour(ptTile, NULL, 0xFFFF);
    //! 向指定box区域填充黑色
    arm_2d_rgb16_fill_colour(ptTile, &tBox, 0x0000);
    //! 更改box的坐标,大小不变
    tBox.tLocation.iX -= 10;
    tBox.tLocation.iY -= 10;
    //! 向修改后的box指定区域填充蓝色,并且使用 50%(128/255)的透明效果
    arm_2d_rgb565_fill_colour_with_alpha(   
        ptTile, 
        &tBox, 
        (arm_2d_color_rgb565_t){0x001F},     //填充蓝色
        128);      //!< 透明度

    return arm_fsm_rt_cpl;
}

以上就绘制了如下图的一个简单图标:

4324a92e-011c-11ed-ba43-dac502259ad0.png

这里是利用”arm_2d_rgb16_fill_colour”和” arm_2d_rgb565_fill_colour_with_alpha”两个API进行矩形的绘制,可以看出这是16位RGB格式的色彩填充,当然库中也提供了32位RGB格式以及8位图的绘制函数;库中还提供”arm_2dp_rgb16_draw_point”的画点函数和”arm_2dp_rgb16_draw_pattern”的画图函数。当然,想做一个图形驱动标准,肯定不止有draw这么基础的能力,Alpha blending,Rotation等一系列图形处理的功能都需要支持。

2. 做一个表盘界面

现在,将各项功能综合运用起来,做一个图形界面试试。

首先,掏出我们“祖传”LOGO,将其转化为特定格式的数组,用的是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文件放到工程中。

435be77c-011c-11ed-ba43-dac502259ad0.png

除了背景,其余的表盘以及指针等图像文件我们就用Arm-2D提供的例程里的。

在工程栏中新建”asset”分组,将” ..Arm-2Dexamplescommonasset”中除了”background.c”之外的c文件都选进去,并将之前生成的”logo.c”文件也加入其中,以logo图作为本次的背景。这一步是将所需的贴图都加进去。

接着,按照”watch_panel”的工程布局将需要的文件添加:”example_gui.c”和”example_gui.h”,并且依据工程修改主函数、补齐相关的配置。

  1. 程序运行时,先进行相关的硬件配置及初始化操作,再进行Arm-2D的初始化” arm_2d_init()”,到这里都和上一节画一个矩形是一样的;
  2. 接着,我们需要对绘制界面中刷新层进行初始化“example_gui_init()”,函数定义在“example_gui.c”中;
  3. 进行PFB的配置,与上节不同的是,将” pfb_draw_handler”改成“pfb_draw_background_handler”,而” pfb_draw_handler”需要留到后面进行图形绘制用;
  4. 在PFB配置完成后,调用PFB任务“arm_2d_helper_pfb_task(&s_tExamplePFB,NULL)”,其中第二个参数为所需刷新的脏矩阵(DirtyRegions)区域,“NULL”则表示需要全屏刷新;
  5. 调用图形绘制函数“ARM_2D_HELPER_PFB_UPDATE_ON_DRAW_HANDLER(&s_tExamplePFB, &__pfb_draw_handler);”,其中绘制的部分都在“draw_handler”中的” example_gui_refresh”函数中,对之前添加进工程的贴图进行各种操作就在这里进行,具体可见“example_gui.c”;
  6. 最后,通过“while(1)”使程序运行在“display_task”中,对显示屏指定区域的刷新、图像的一些更新都在此实现。

经过以上的一通操作之后,效果如下动图所示:

436b5630-011c-11ed-ba43-dac502259ad0.gif

从上可以看出,此工程中用了bit blit, alpha blending, rotation等效果:
  1. logo滚动背景利用一定范围内不断变换坐标的贴图来实现;
  2. 表盘利用”arm_2d_rgb565_alpha_blending_with_colour_masking”确定指定的透明度颜色蒙版来实现;
  3. 两个旋转齿轮以及一根旋转表针,通过” arm_2dp_rgb565_tile_rotation_with_alpha”区分透明度以及确定旋转中心来分别实现。

四、总结

至此,基本的Arm-2D图形绘制功能在i.MX RT1050-EVK上的实现就介绍完了。

本文只是简单移植一个包含Arm-2D绘图库实现某些动画效果的例子,已经可以看到其多样的功能,至于更多的一些效果,留给我们的想象空间还很足......

本文只是开篇,后续,还会有对于Arm-2D在i.MX RT上更多的应用介绍。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    17117

    浏览量

    350934
  • ARM
    ARM
    +关注

    关注

    134

    文章

    9082

    浏览量

    367343
  • 图形界面
    +关注

    关注

    0

    文章

    37

    浏览量

    7365

原文标题:在i.MX RT平台上部署Arm-2D

文章出处:【微信号:pzh_mcu,微信公众号:痞子衡嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【大联大品佳 NXP i.MX RT1050试用申请】基于 NXP i.MX RT1050工业机器人开发

    项目名称:基于 NXP i.MX RT1050工业机器人开发试用计划:1,熟悉板子硬件,RT1050驱动板子硬件,做GPIO测试,串口测试,SPI测试,IIC测试,PWM测试,每种出一片报告。
    发表于 08-10 18:23

    【大联大品佳 NXP i.MX RT1050试用申请】i.MX RT1050 3D打印机控制器

    项目名称:i.MX RT1050 3D打印机控制器试用计划:申请理由本人在开源硬件行业有五年多的学习和开发经验,曾设计多款FDM,SLA,LCD 3D打印机控制板,参与公司3
    发表于 08-10 18:23

    【大联大品佳 NXP i.MX RT1050试用申请】使用NXP i.MX RT1050开发板设计一款低成本CAN数据采集仪

    项目名称:使用NXP i.MX RT1050开发板设计一款低成本CAN数据采集仪试用计划:目前的CAN数据采集仪通常使用的是CAN采集仪+上位机的方法,这种方案非常不便捷,需要带电脑现场去作业
    发表于 08-10 18:24

    i.MX RT1050平台的相关资料推荐

    SylixOS 正式支持 i.MX RT1050平台发布于2018年06月22日什么是 i.MXRT1050i.MX RT1050 是 N
    发表于 11-29 07:19

    arm cortex处理器能用Arm-2D实现图形界面设计吗

    如何使用Arm-2D在小资源Cortex-M处理器芯片中实现图形界面,非arm cortex处理器能用Arm-2D吗?
    发表于 08-04 14:14

    如何使用Arm-2D在小资源Cortex-M处理器芯片中实现图形界面

    在如何使用Arm-2D在小资源Cortex-M处理器芯片中实现图形界面中,效果器显示效果和MDK调试代码怎么关联?模拟器不是单独运行在PC环境里的吗?
    发表于 08-26 14:40

    Arm-2D对LCD接口有要求吗

    在如何使用Arm-2D在小资源Cortex-M处理器芯片中实现图形界面中,Arm-2D对LCD接口有要求吗,比如8位8080-i接口还是24位RGB接口?
    发表于 09-28 10:19

    Arm-2D对LCD接口有要求吗

    在如何使用ARM-2D在小资源Cortex-M处理器芯片中实现图形界面中,Arm-2D对LCD接口有要求吗,比如8位8080-i接口还是24位RGB接口?
    发表于 10-21 14:08

    如何使用emWin的API绘制图形

    界面( HMI) 很简单。 这个示例代码使用 M480 MCU , 使用 emWin 的 API 来绘制图形, 可以用作更改面板文字编辑值的按钮。 emWin 可以轻松地执行如何使用图形
    发表于 08-23 07:37

    M480使用emWin的API绘制图形

    界面( HMI) 很简单。 这个示例代码使用 M480 MCU , 使用 emWin 的 API 来绘制图形, 可以用作更改面板文字编辑值的按钮。 emWin 可以轻松地执行如何使用图形
    发表于 08-30 08:58

    【044】SylixOS 正式支持 i.MX RT1050平台

    SylixOS 正式支持 i.MX RT1050平台发布于2018年06月22日什么是 i.MXRT1050i.MX RT1050 是 N
    发表于 11-19 12:51 14次下载
    【044】SylixOS 正式支持 <b class='flag-5'>i.MX</b> <b class='flag-5'>RT1050</b>平台

    RT-Thread & NXP 发布 i.MX RT 系列 BSP 新框架

    前言i.MX RT 是 NXP 推出的跨界处理器系列。该系列下又包括 i.MX RT1020、i.MX
    发表于 12-07 13:06 2次下载
    <b class='flag-5'>RT</b>-Thread & NXP 发布 <b class='flag-5'>i.MX</b> <b class='flag-5'>RT</b> 系列 BSP 新框架

    移植Arm-2Di.MX RT1050-EVKB绘制图形界面

    众所周知,i.MX RT系列是MCU中的性能强者,超高的主频、丰富的外设以及足够大的存储使其能轻松应用于各类领域。其中,在图像视频方面,i.MX RT1050及以上系列,集成了PXP
    的头像 发表于 06-23 09:33 2185次阅读

    基于 NXP i.MX RT1050 的 3D 打印机方案

    MCU-Healer 是基于 NXP i.MX RT1050 做的 3D 打印机方案,该方案主控 MCU i.MX RT1050是一颗 Co
    的头像 发表于 04-06 15:06 1190次阅读
    基于 NXP <b class='flag-5'>i.MX</b> <b class='flag-5'>RT1050</b> 的 3<b class='flag-5'>D</b> 打印机方案

    i.MX RT1050上如何实现双大容量存储(MSC)设备

    i.MX RT1050上如何实现双大容量存储(MSC)设备
    的头像 发表于 10-30 17:08 626次阅读
    在<b class='flag-5'>i.MX</b> <b class='flag-5'>RT1050</b>上如何实现双大容量存储(MSC)设备