嵌入式系统与单片机|技术阅读
登录|注册

您现在的位置是:嵌入式系统与单片机 > 技术阅读 > 玩转Arm-2D(一)PFB性能测试与绘制方块

玩转Arm-2D(一)PFB性能测试与绘制方块

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*8大小的PFB也可以支持任意大小的屏幕,最关键的是用户界面API是不用关心PFB的大小的,Arm-2D都为我们弄好了,我们可以假装拥有完整的Frame Buffer。


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


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

Arm-2D的部署教程如下:


我们的测试硬件如下:

单片机

树莓派PICO,

CPU频率125MHz

屏幕
SPI  240*240LCD


在app_cfg.h中修改PFB的大小,如下:

#define PFB_BLOCK_WIDTH 240#define PFB_BLOCK_HEIGHT 240
PFB
ZI-data
FPS30FreqFPS
240*240
156192
242.01
15.64
120*12069792
256.22
14,68
12*12
41280
470.33
7.125
120*12
43872
300.53
12.80
120*2
41472
433.12
8.115
8*8
41120
694.57
5.185
  • 我们很容易发现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函数为带透明度填充一个矩形。


程序运行效果如下视频演示:



原创不易,如果你喜欢我的公众号、觉得我 文章对你有所启发,

请务必“点赞、收藏、转发”,这对我很重要,谢谢!

欢迎订阅    嵌入式小书虫