傻孩子(GorgonMeducer) · 2022年01月13日

【第三方测评】玩转Arm-2D(一)PFB性能测试与绘制方块

以下文章来源于嵌入式小书虫 ,作者FledgingSu 支离苏
image.png

1、Arm-2D是什么

Arm-2D是arm公司开源的一个嵌入式软件,专门为小资源单片机提供显示驱动,此软件的github 地址如下:
https://github.com/ARM-software/EndpointAI
那它为什么可以为小资源单片机提供显示驱动呢?

这主要是他提供了一个简单通用的PFB技术,这样就可以根据资源的大小灵活的分配显示缓冲区的大小了。

那么PFB是什么呢?

2、部分帧缓存PFB(Partial Frame Buffer)

很多单片机的ram通常都不会很大(4K ~ 32K),然而一个常见的320 * 240 的16位色的LCD屏幕的完整缓存就需要153.6KB RAM,这时候小资源单片机拥有一块完整的缓存就不可能了,部分帧缓存PFB技术就是为了解决这个问题。而Arm-2D的PFB技术是可以支持任意大小的,哪怕只有8 x 8大小的PFB也可以支持任意大小的屏幕,最关键的是用户界面API是不用关心PFB的大小的,Arm-2D都为我们弄好了,我们可以假装拥有完整的Frame Buffer。

3、部署Arm-2D与PFB性能测试

Arm-2D 的PFB技术这么好,还省RAM,那他有什么不足吗?显而易见的就是性能问题,我们用的PFB越小,屏幕刷新的速率就越慢,因为他本身就是用时间来换空间的。好,接下来我们就测试下不同的PFB大小对性能的影响到底有多大。

Arm-2D的部署教程如下:
一网打尽Arm-2D的部署教程

我们的测试硬件如下:
image.png
在app_cfg.h中修改PFB的大小,如下:

#define PFB_BLOCK_WIDTH  240
#define PFB_BLOCK_HEIGHT 240

image.png

  • 我们很容易发现PFB越大,所需的ZI-data越多,FPS越大,性能越好。
  • 性能和PFB大小的关系不是成倍的,比如前两行,PFB变为四分之一,而性能却只下降了1FPS。
  • 第三行PFB(12 * 12)是整个屏幕的400分之一,性能才下降了一半,是不是感觉PFB技术还是挺不错的。
  • 注意,在实际使用时, 要自己根据硬件进行测试,选择合适 的PFB,不仅节省内存,性能也不会下降太多。

4、绘制方块和设置dirty List并显示字符

dirty List脏矩阵列,简单说就是一个由用户指定的刷新区域列表——你让PFB只刷哪些区域,它就只刷哪些区域,也就是局部刷新。因为我们每次不会修改整个屏幕的数据,一般都是局部修改,有了这个dirty List,我们就可以只刷新修改了的区域,这样就可以节省刷屏时间,提升性能。

设置dirty List的程序如下:

void display_task(void)
{
  /*! define dirty regions */
  ||定义一个dirty List链表
  IMPL_ARM_2D_REGION_LIST(s_tDirtyRegions, const static)
  ||添加一个128*64 的区域
  ADD_REGION_TO_LIST(s_tDirtyRegions,
        .tLocation = {
            .iX = 20, 
            .iY = 20,
        },
        .tSize = {
            .iWidth = 128,
            .iHeight = 64,
        },
    ),
   ||添加第二个128*64 的区域         
   ADD_REGION_TO_LIST(s_tDirtyRegions,
      .tLocation = {
          .iX = 20, 
          .iY = 100,
      },
      .tSize = {
          .iWidth = 128,
          .iHeight = 64,
      },
  ),
 ||添加第三个(也是最后一个)240*64 的区域 
  /* a region for the status bar on the bottom of the screen */
  ADD_LAST_REGION_TO_LIST(s_tDirtyRegions,
      .tLocation = {0,170},
      .tSize = {
          .iWidth = 240,
          .iHeight = 64,
      },
  ),
  ||添加完成调用宏
  END_IMPL_ARM_2D_REGION_LIST();
   ||刷新dirty List区域
    //! call partial framebuffer helper service
    while(arm_fsm_rt_cpl != arm_2d_helper_pfb_task(                                
        &s_tExamplePFB, 
        (arm_2d_region_list_item_t *)s_tDirtyRegions));                             
}
  • 注意最后一个区域要用ADD_LAST_REGION_TO_LIST宏添加。
  • 函数arm_2d_helper_pfb_task第二个参数传人dirty List就可以局部刷新了。

在区域中显示字符的函数如下:

void example_gui_refresh(const arm_2d_tile_t *ptTile, bool bIsNewFrame)
{
  arm_2d_region_t tBox = {
    .tLocation = {20,20},
    .tSize = {128, 64},
  };
   static int16_t xx = 0;
   ||填充黑色背景 
   arm_2d_rgb16_fill_colour(ptTile, NULL, GLCD_COLOR_BLACK);
   ||在第一块区域中显示字符         
   arm_2d_rgb16_fill_colour(ptTile, &tBox, GLCD_COLOR_BLACK);
   LCD_donghua();      
    //! 在box指定的区域填充蓝色,并且使用 50%(128/255)的透明效果
   arm_2d_rgb565_fill_colour_with_alpha(   
        ptTile, 
        &tBox, 
        (arm_2d_color_rgb565_t){GLCD_COLOR_BLUE}, 
        58);      //!< 透明度        

   ||在第二块区域中显示字符    
   if (bIsNewFrame) {
      tBox.tLocation.iX = 20;
      tBox.tLocation.iY = 100;
   }  
   arm_2d_rgb16_fill_colour(ptTile, &tBox, GLCD_COLOR_BLACK);
   LCD_donghua2();
    
   ||在第三块区域中显示汉字  
   for(uint8_t i = 0; i < 6; i++){
        print_chinese(ptTile,"嵌入式小书虫", xx);
   }
   xx--;
   if(xx < -288){
      xx = 239;
   }
}
  • arm_2d_rgb16_fill_colour函数为填充一个矩形。
  • arm_2d_rgb565_fill_colour_with_alpha函数为带透明度填充一个矩形。
首发:裸机思维
作者:FledgingSu 支离苏

专栏推荐文章

如果你喜欢我的思维,欢迎订阅裸机思维
推荐阅读
关注数
1462
内容数
107
探讨嵌入式系统开发的相关思维、方法、技巧。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息