工业和家用电器市场中的各种应用要求使用数学运算来实现不同的算法和计算。基于 Cortex®-M0 的单片机包含加法、减法和乘法指令。Cortex-M0 架构没有用于除法运算的汇编指令,除法逻辑可以根据不同的编译器而变化。基于 Arm® Cortex-M0 的单片机(MCU)具有一个可配置选项,可通过该选项使用快速乘法器进行乘法运算。基于该可配置选项,乘法运算可以为单个周期指令到最多 32 个周期指令不等。
SAMC21(一款 Cortex-M0 MCU)非常适合需要数学计算的应用。SAMC21 MCU 具有可进行乘法运算的快速单周期乘法器选项,还具有一个新的外设,称为除法和平方根加速器(Division and Square Root Accelerator,DIVAS),可用于执行快速除法和平方根运算。
1. 概念
适用于 Arm 架构的应用程序二进制接口(Application Binary Interface,ABI)包含一系列标准,其中有些是开放的标准,还有一些是 Arm 架构专用标准。ABI 可管控各种基于 Arm 的执行环境中二进制文件和开发工具的互操作。支持 Arm MCU 的编译器需符合这些标准。这些标准的其中一项是适用于 Arm 架构的运行时 ABI。此标准为 ABI 指定辅助函数,使之能够支持 C、C 和算术运算。对于除法,编译器会用各自的库代码替换除法和模运算符(即,使用重复减法来实现除法)。该库代码将数百个字节添加到代码存储器,MCU 消耗 50 到 400 之间任意数量的时钟周期,具体取决于操作数的大小。编译器可通过过载运行时ABI 辅助方法来使用 DIVAS 功能。DIVAS 展现出的性能优于编译器除法(即,比除法 65535/3 少 50 个时钟周期)。DIVAS 支持整数平方根运算,而不需要任何额外的库依赖关系。
注: 模运算符使用除法来取得余数,因此需要过载。DIVAS 的性能表现可能会随着被除数和除数的值而变化。
2. 解决方案/实现
DIVAS 只支持 32 位整数除法。用于除法运算的运行时 ABI 辅助方法过载,以便编译器了解除法应使用DIVAS 功能进行除法。根据运行时 ABI 标准,32 位整数除法函数在 r0 中返回商,或在{r0, r1}中返回商和余数。
在下面的示例中,使用 Arm 专用原型表示法描述二值返回函数。
注: 有些编译器可以使用 64 位有符号/无符号整数作为返回类型,而不是 idiv 或 uidiv 结构。
int __aeabi_idiv(int numerator, int denominator);
unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator);
typedef struct { int quot; int rem; } idiv_return;
typedef struct { unsigned quot; unsigned rem; } uidiv_return;
__value_in_regs idiv_return __aeabi_idivmod(int numerator, int denominator);
__value_in_regs uidiv_return __aeabi_uidivmod(unsigned numerator, unsigned denominator);
注:
ASFv3 框架为 DIVAS 驱动程序提供支持。DIVAS ASF API 包含整数除法、模和平方根的 API。将符号定义 DIVAS_OVERLOAD_MODE 设置为 true,即可帮助 DIVAS 的 ASF 驱动程序中过载的 ABI 辅助方法来执行内部除法运算。包含运行时 ABI 辅助方法的驱动程序使用 DIVAS ASF 驱动程序 API 进行过载。
图 2-1. DIVAS 除法运算
函数可以使用 DIVAS 平方根功能,不再需要使用基于数学库浮点运算的函数调用。
图 2-2. DIVAS 平方根运算
DIVAS 可用于以下应用场景:
• ADC 和振荡器的运行时校准,用于微调工业和电机控制应用中 ADC/振荡器输出的性能。
• 需要更快 PID 环的工业控制应用。
提示:
被零除:Cortex-M0 是不包括除法指令的 Armv6-M 架构,因此没有硬件异常。用户可以通过确认分母是否为零来进行验证,基于此,可以使用引发 API 来引发软件用户异常,或者提供默认值(零或被除数)作为输出。请参见 了解 GCC 编译器支持的信号/引发 API 的信息。
该除法可能导致有符号位溢出:当被除数-2147483648(位模式 0x80000000)除以值为-1 的分母时,输出数 2147483648 用符号表示,没有值。以上是一种特殊情况,用户可以根据应用需求定义实现方式(即,可以返回被除数或默认值)。
从 ISR 和主上下文进行的除法/模运算:如果同时从 ISR 和主上下文进行除法运算,则过载方法应受到中断锁定的保护。那么,在每个过载方法开始和结束时,实现应包含全局中断禁止和全局中断允许方法。
浮点除法与长除法:Arm Cortex-M0 没有浮点单元(floating-point unit,FPU),而且 DIVAS 只支持 32 位整数除法。编译器继续使用自己的库代码来执行浮点除法和长(64 位)除法,而不是使用 DIVAS。