Arm_2D移植与入门

在当今竞争激烈的市场中,嵌入式设备不仅需要高性能,还需要具有吸引力的用户界面。图形用户界面(GUI)在提升用户体验方面起着至关重要的作用。为了满足这一需求,Arm 开发了 Arm_2D,并且在Github上发布了一个专为嵌入式系统设计的高效 2D 图形库:

https://github.com/ARM-software/Arm-2D

1. 什么是Arm_2D?

Arm_2D 是 Arm Limited 提供的一个用于嵌入式系统的 2D 图形库。它专门设计用于在基于 Arm 架构的微控制器上提供高效的图形渲染能力。Arm_2D 库优化了性能和内存使用,使其非常适合资源受限的嵌入式环境;它不仅能够提供基本的2D图形渲染功能,还能够支持复杂的图形操作,如平移、缩放、旋转等。它通过简化GUI开发流程,让开发者能够快速地为Arm架构的MCU开发出吸引人的界面。

2. Arm_2D的主要特点与优势

  • 多级缓存系统

    Arm_2D 引入了多级缓存机制,允许开发者实现部分屏幕刷新和多缓冲技术。这不仅减少了不必要的渲染,还显著降低了系统的功耗。

  • 硬件加速

    Arm_2D 能够利用 Arm 微控制器中的图形加速硬件,如 GPU 或专用 2D 图形引擎,从而提高渲染性能。

  • 丰富的图形操作

    Arm_2D 提供了广泛的图形操作,包括但不限于位图复制、颜色填充、透明混合、旋转和缩放。这些操作为开发者提供了强大的工具,以实现复杂的图形效果。

  • 可配置性

    Arm_2D 的设计考虑了不同硬件平台和应用场景的需求,因此它具有很高的可配置性,允许开发者根据具体的项目需求进行定制。

  • 易用性

    Arm_2D 的 API 设计简洁直观,使得即使是初学者也能快速上手。它简化了复杂图形效果的实现过程,让开发者能够专注于创新而非底层细节。

  • 跨平台支持

    虽然 Arm_2D 最初是为 Arm 架构设计的,但它的跨平台特性意味着它可以被移植到其他架构上,增加了它的适用性。

  • 开源许可

    Arm_2D 在 Apache 2.0 许可下开源,这意味着开发者可以免费使用、修改和分发该库,同时享有知识产权的保护。

3. Cube MX 配置

在进行Arm_2D移植前我们先要进行一些初始化;

  • 配置时钟源
    在这里插入图片描述

  • 配置SPI
    在这里插入图片描述

  • 配置时钟树

在这里插入图片描述

4. Arm_2D移植

我们如何才能在程序上部署Arm_2D呢?,有两种方式,一种是直接利用Github里提供的源码移植,获取链接已经放在上面,另一种是利用CMSIS-PACK包移植,由于CMSIS-PACK包移植只需我们点点鼠标就可以配置完成编译通过,所以接下来我就已CMSIS-PACK包来进行移植,另一种方法大家自己进行尝试。

4.1 准备工作

首先我们准备一个工程,并且确保该工程已经实现了基本的LCD初始化;(我这里用的是STM32F103ZET6进行移植)

提供一个向LCD指定区域传送位图的函数,其在Arm_2D中的原型如下:

void Disp0_DrawBitmap (uint32_t x, 
                       uint32_t y, 
                       uint32_t width, 
                       uint32_t height, 
                       const uint8_t *bitmap)
  • uint32_t x:位图绘制起始点的 x 坐标(水平位置)。

  • uint32_t y:位图绘制起始点的 y 坐标(垂直位置)。

  • uint32_t width:要绘制的位图图像的宽度。

  • uint32_t height:要绘制的位图图像的高度。

  • const uint8_t *bitmap:指向位图数据的指针。数据格式通常是一个字节数组,其中包含了位图图像的像素信息。

4.2 获取pack包

MDK 中部署 Arm-2D的第一步是获取对应的 cmsis-pack。你可以直接通过Pack Installer中找到Arm-2D

在这里插入图片描述

也可以通过KEIL官网获取:

https://www.keil.arm.com/packs/arm-2d-arm/versions/

在这里插入图片描述

但是官网这里提供的是1.1.5版本的,而我用的是1.1.6,相对上一版本而言1.16拥有众多新特性等,推荐使用最新版,要想获得最新的版本,推荐向 【裸机思维】 公众号发送关键字 “Arm-2D” 获取网盘链接。

还可以通过 https://github.com/ARM-software/Arm-2D 获取:

在这里插入图片描述

获得 Arm-2Dcmsis-pack后,可以直接双击进行安装之后进行一系列无脑操作,(这里强烈推荐将MDK安装最新版本,以避免一系列不必要的麻烦,节省时间)。

4.3 部署cmsis-pack

4.3.1 加入组件

点击 Manage Run-Time Environment快捷按钮来打开RTE配置窗口:

在这里插入图片描述

点击并展开Acceleration并根据下图勾选以下组件:

在这里插入图片描述

  • CoreArm-2D的核心(必选)
  • Alpha-Blending:大部分与透明度相关的操作,比如基于蒙版的拷贝、透明图层合成、透明色块填充等等
  • Transform:旋转、缩放等操作(支持蒙版、抠图和透明度)
  • Filter:渲染滤镜(目前支持抗锯齿和模糊效果)

为了简化我们与LCD显示驱动进行对接,需要勾选以下服务:

  • FPBPartial Frame-Buffer模块,支持部分刷新的核心组件
  • Display Adapter:一个使用 PFB 来适配 LCD 底层驱动的代码模板,帮我我们快速在上层绘图和底层LCD刷新之间建立桥梁。一般来说 Display Adapter 与 屏幕是一一对应关系:如果你有一块屏幕,这里就选“1”,如果你有两块屏幕,这里就选“2”,以此类推。

由于 Display Adapter 依赖了一些额外(Extra)的模块,因此,如果你只勾选了上述的部分,你会在窗口中看到橙色的警告:
在这里插入图片描述

这里警告的含义是说:Display Adapter依赖了模块 ControlsLCD ASCII Printf,但你没有勾选它们。简单的单击左下角的 Resolve 按钮,RTE会自动帮你勾选上所依赖的模块。

在这里插入图片描述

点击OK按钮完成组件添加,后续还可过此来添加demo组件。

为了方便后续的开发,强烈推荐下载并安装 perf_counter 模块,大家可以通过【裸机思维】公众号发送关键字“perf_counter”来获取对应的 cmsis-pack

现在完成后,同样是打开RTE,找到 Utilities,并勾选 perf_counter 中的 Core,推荐以 Source ** 形式进行部署, 如出现橙色警告,还是点击Resolve**按钮来解决

在这里插入图片描述

如果不使用perf_counter来为Arm-2D提供时间基准服务,则需要手动实现下列两个函数:

extern
int64_t arm_2d_helper_get_system_timestamp(void);

extern
uint32_t arm_2d_helper_get_reference_clock_frequency(void)

其中:

  • arm_2d_helper_get_system_timestamp() 要返回一个int64_t类型的时间戳,它的精度至少要是10KHz级别,并且不允许(在你我的有生之年内)溢出;
  • arm_2d_helper_get_reference_clock_frequency() 要返回这个时间戳的实际频率,同样,根据要求,它至少要大于等于10KHz

推荐使用 perf_counter ,不需要那么麻烦去实现两个函数,并且在最新的版本中 perf_counter 已经解绑了SysTick——允许用户将perf_couner移植到任意架构下、使用任意精度的定时器了

4.3.2 配置编译环境

使用Arm Compiler 6(armclang)进行编译,因为 Arm Compiler 5(armcc) 已经不在支持Arm_2D了,需要打开对C11GNU扩展的支持,即直接在"Language C"中选择“gnu11”:

在这里插入图片描述

此外,在使用Arm Compiler 6时,除调试专用的-O0以外,请务必开启Link-Time-Optimization。Arm-2D推荐的优化选项是:

  • 如果只在乎性能不在乎尺寸,请选择-Ofast + Link Time Optimization

  • 如果只在乎尺寸完全不在乎性能,请选择-Oz + Link Time Optimization

  • 如果在乎尺寸和性能的平衡,请选择-Os + Link Time Optimization

  • 不开Link Time Optimization的Arm Compiler 6 无法拉开和 gcc 的差距。开了Link Time Optimization的 Arm Compiler 6 可以瞬间超越(或者至少战平)IAR。

由于Arm-2D依赖CMSIS ,可以通过配置MDK的RTE的方式来获得最新版本CMSIS的支持。

  1. 点击工具栏最右边的按钮打开Pack Installer,找到ARM::CMSIS,并确保它显示“Up to date”,如果没有就单击对应的按钮进行更新。Arm-2D所依赖的CMSIS版本不得低于5.7.0(如果你要用Cortex-M55,则版本不得低于5.8.0),如下图所示:

在这里插入图片描述

  1. 确保显示“Up to date”后再打卡RTE,找到CMSIS,并勾选CORE和DSP,并将DSP下的Source选项勾选,这将允许我们直接使用源代码的形式来编译CMSIS-DSP的库。
    在这里插入图片描述

  2. 如果不确定CMSIS是都为最新版本,可以点击底部的Select Packs按钮,如果看到顶部 “Use latest Software Packs for Target” 被勾选,基本上就不用担心它啦,依次点击🆗关闭就可以了,点击编译,可以看到成功完成编译,这样我们就将CMSIS编译进程序里了。

在这里插入图片描述

4.3.3 模块配置

在工程管理器中展开 Acceleration,并找到新加入的显示驱动适配器文件(arm_2d_disp_adapter_0.h)

在这里插入图片描述

双击打开后,在编辑器的左下角选择 Configuration Wizard

在这里插入图片描述

进入图形配置界面:

在这里插入图片描述

进入后根据自己的屏幕填写正确信息:

  • 颜色位数(Screen Colour Depth)
  • 横向分辨率(Width of the screen)
  • 纵向分辨率(Height of the Screen)
  • 部分刷新缓冲块的宽度(Width of the PFB Block),一般优先考虑为整行或者1/2行像素的宽度
  • 部分刷新缓冲块的高度(Height of the PFB Block),一般推荐为1/10屏幕像素高度。在RAM较为紧缺时,考虑8或者1。
  • 进行帧率计算时,平均多少帧做一次数据更新(Number of iterations),默认是30,选0将关闭帧率实时计算功能
  • 实时帧率统计模式(FPS Calculation Mode),默认为 Render-Only FPS(只计算Arm-2D渲染部分的帧率)而Real FPS则计算实际的帧率。
  • 如果你的LCD控制芯片无法以硬件的方式交换RGB565像素的高低字节,则你可能需要勾选 Swap the high and low bytes 通过软件来实现这一功能。

填写完信息后保存,之后在Acceleration中找到 arm_2d_cfg.h并打开:

之后同样打开它的 Configuration Wizard 图形配置界面:

在这里插入图片描述

由于我们用到了 Extra中的一些模块,比如 ContolsLCD ASCII Printf,因此需要提供对应的信息:比如屏幕的颜色位数、分辨率和 printf 打印行缓冲的大小(默认值是64个ASCII字符)。

对于 Arm-2D General Configuration 中的一些选项,这里有必要做一下说明:

  • Enable Asynchronous Programmers’ model support:目前推荐关闭
  • Enable anti-alias support for all transform operations:使能旋转、缩放操作的抗锯齿功能
  • Enable Support for accessing individual Colour channels:当你的目标屏幕是 RGB888,而你又需要支持 PNG 图片时推荐打开。

Patches for improving performance 中都是一些通过Hack掉某些可能用不到的特性或者功能来换取性能的选项。推荐做法是:

  • 保持默认选项

  • 在完成应用后依次尝试:如果对应用没有明显的影响,就勾选以换取一定的性能提升。

Benchmark 中是一些跑Arm-2D基准测试相关的选项。这里,我们需要设置屏幕的分辨率。如果你的Flash尺寸小于512K,则务必勾选Use Tiny mode to run benchmark——它将开启TINY模式,确保哪怕最低 64K Flash的芯片也可以运行最小的2D基准测试

4.4 添加代码

添加完代码后,我们的移植工作就算是完成了;不出意外的话,我们就可以看到屏幕上会有显示;

首先再mian.c函数里添加源代码文件中包含的头文件:

#include "arm_2d_helper.h"

并在 **main()**函数中完成对 arm-2d 的初始化:

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  //MX_TIM4_Init();
  /* USER CODE BEGIN 2 */
	
  HAL_GPIO_WritePin(GPIOA, PWM_Pin, GPIO_PIN_SET);//点亮背光
  lcd_init_320x480(0);//屏幕初始化
	
	arm_irq_safe {
			arm_2d_init(); // 初始化 arm-2d
	}
	
	// 初始化 Display Adapter 0
	disp_adapter0_init();
    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
      
    /* USER CODE BEGIN 3 */
    // 执行 Display Adapter 的刷新任务
    disp_adapter0_task();
  }
  /* USER CODE END 3 */
}

编译、下载,如果一切顺利,你应该可以在屏幕上看到类似如下的画面:

在这里插入图片描述

如果你看到画面中的载入圈圈并未旋转,则可以按照以下思路来检查:

  • 有没有部署 perf_counter

  • 如果没有部署perf_counter,有没有按照要求实现函数 arm_2d_helper_get_system_timestamp()arm_2d_helper_get_reference_clock_frequency()

  • 如果部署了 perf_counter,检查是否正确初始化了perf_counter。在Cortex-M平台下,则应该检查运行 disp_adapter0_task() 的时候,SysTick是否处于运行状态

  • 如果还没有得到解决,看一下CubeMX时钟处是否为SisTick;

在这里插入图片描述

5. 移植常见问题

  • 编译时报告某些系统的intrinsics重复定义,比如__set_PRIMASK 等等

这是由于工程中自带的cmsis版本太低,且与RTE所部署的cmsis冲突导致的。

解决办法:打开工程配置页面,再 Include Paths 处删除老版本CMSIS的头文件路径即可,以本工程为例,…/Drivers/CMSIS/Include就是存放老版本的地方。

  • 提示找不到__aeabi_assert

这是由于我们在工程中选择了 microLib,而 microLib 没有为 assert.h 提供底层实现导致的。添加如下代码即可:

#include "arm_2d.h"
#include "cmsis_compiler.h"

#if defined(__MICROLIB)
void __aeabi_assert(const char *chCond, const char *chLine, int wErrCode) 
{
    ARM_2D_UNUSED(chCond);
    ARM_2D_UNUSED(chLine);
    ARM_2D_UNUSED(wErrCode);
    while(1) {
        __NOP();
    }
}
#endif

还可以通过CMSIS-Pack包配置:

打开RTE,找到Compiler选项下I/O选项下的STDERR勾选为ITM,保存重新编译即可;

在这里插入图片描述

  • 提示找不到 Disp0_DrawBitmap

你选择 Display Adapter 服务时,需要用户提供一个向 LCD 刷新数据的函数。当你有多个屏幕时,需要在 RTE 里为 Display Adapter 选择对应的数量:

在这里插入图片描述

然后给每个Display Adapter 添加一个属于自己的底层刷新函数;

  • 出现Hardfault

检查栈(Stack)的大小,推荐在 0xC00(3K)以上为易,HEAP在1K以上。

  • 屏幕颜色不对,要注意需要进行字节交换
  • 31
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值