本帖最后由 zhanzr21 于 2022-8-16 20:49 编辑
#申请原创# 拿到凌鸥科技的LKS32AT085的开发板, 分享一下. 先说一声, 本文主要对DSP这个功能比较感兴趣, 其他功能不会特别关注.先晒晒照片:
板子分为两部分: 核心板+电机驱动板
AEC-Q100认证
核心板上即为评测的主角芯片LKS32AT085, 这是一个Cortex M0的MCU. 它的功耗/频率/外设/存储都跟一般的MCU差不多, 但是特别之处在于它是通过 AEC-Q100 检测认证的车规级别芯片. 通过AEC-Q100的芯片可以用于汽车环境, 否则是不合规的. 疫情刚刚来临的一两年内, 车规芯片价格曾经被炒作到平时的几百倍, 直到今天普通芯片基本上已经不缺货了, 车规级别的MCU依旧缺货. 车规级别芯片与普通芯片的差别在于生产环节, 测试环节的严格要求, 如果说功能, 车规级别芯片则与普通芯片类似.
同样是AEC-Q100, 也分为几个子级别, 根据适用工作温度范围而定. 手上的这个芯片工作范围为: = -40~125° 对应Grade 1.
Grade | Ambient Operating Temperature Range | 0 | -40°C to +150°C | 1 | -40°C to +125°C | 2 | -40°C to +105°C | 3 | -40°C to +85°C |
除了AEC-Q100之外, 还有
AEC-Q101 - 汽车环境用的功率器件, 二极管, MOSFET, 整流桥等等.
这个芯片从外设资源来看, 主要应用于车载环境的电机控制, 电机控制涉及到很多数**算, 所以带了一个叫做DSP的外设.
这个外设有两种模式:
被动调用时, 相当于挂在总线上的一个外设. 用于加速数**算.
自主运行时, 相当于一个协处理器, 主处理器配置好算法, 协处理器运算完了发生中断, 主处理器取结果, 更新计算任务.
它能完成的运算类型有:
加法、乘累加、移位、饱和等单周期算术指令,
以及除法、开方、三角函数等多周期算术运算指令
有同学可能要问, 这跟FPU什么区别, 答案是这个跟FPU功能有一些重叠, 但是跟FPU差别也很明显.
1. FPU是CPU内核的一部分, Cortex系列的, M4才有选择增加FPU的选项, 对于M0, M0+, M3这种内核, 要增加数**算功能, 增加DSP这样的外设较为灵活;
2. FPU主要是对浮点数运算进行加速, 有很大一类控制领域的数**算只需定点精度即可, 纯软件算起来慢, 增加DSP这样的外设刚刚好;
3. FPU对内核的Die尺寸, 复杂度增加过大, 对于汽车领域的芯片, 有很多认证测试要过, 增加的复杂度是很大的成本开销;
4. DSP外设除了像FPU那样同步计算之外,还可以作为协处理器,异步运行, 在控制领域, 运算任务相当比较固定的场景, 相当于增加了一个核心, 这是FPU无法做到的.
下面我们以三角函数sine, cosine为例子,来简单测试下DSP的性能, 本文中DSP作为外设被CPU调用, 下一篇会分享DSP作为协处理器异步执行运算任务的例子.
Q格式的数据
首先先说说Q格式的数据表示方式.
我们知道浮点数由 符号-阶数-尾数 组成. 比如常见的单精度与双精度的浮点数格式如下(其他长度的浮点数也存在,格式类似).
这种格式的优点是表示的范围很大, 但是需要FPU或者软件浮点库识别, 在芯片内部处理时与整数运算规则完全不同.
所以在没有FPU或者不想使用软件浮点库的时候, 可以使用一种叫做Q-格式,也可以叫做定点数的表示方式.
Q格式是一种使用定点数来表示小数的自定义数据格式,
如何解释这个格式由软件的API来定义.
比如ARM DSP库函数中使用的q7_t,使用1bit表示符号, 7bit表示小数/分数部分,表达的范围为:
-1 到 (1-1/128), 每个LSB表示1/128的step,相当于0.0078125
q15_t,表达的范围为:-1 到 (1-1/32767),, 每个LSB表示1/32768的step,相当于3.0517578125e-05
q31_t.....
依次类推
Q格式与浮点数互转, 以Q15为例:
Q15 转 浮点
Q15/32768.0 = Float
如: 输入为0x7FFF
0x7fff/32768 = 0.999969482421875
浮点 转 Q15
int(Float*32768) = Q15
如:输入为0.5
也有网上的工具可做辅助:
Q-format Converter & Calculator (chummersone.github.io)
下文中使用DSP或者ARM的软件DSP库运算三角函数时, 输入与输出均为Q15格式.
使用DSP计算sine与cosine值
首先准备360个测试点的弧度Q15格式, 以下是生成数据的python代码:
for i in range(-180, 180):
print(int(i*32768/180), end=',')
得到一个360点的数组, 对应-π到π的弧度范围: const int16_t angle_array_360_negPi_PosPi[] = {
//数组内容请参考压缩包
};
DSP计算函数(这里只贴代码片段, 完整工程文件见后文连接): for (uint32_t idx = 0; idx < TEST_POINT_NUM; ++idx) {
volatile float sin_Vlaue;
volatile float cos_Vlaue;
int16_t angle_q1_15 = angle_array_360_negPi_PosPi[idx];
sin_cos_result result = dsp_sin_cos_func(angle_q1_15);
}
sin_cos_result dsp_sin_cos_func(int16_t angle_q_1_15) {
sin_cos_result result;
SYS_ModuleClockCmd(SYS_Module_DSP, ENABLE);
DSP_SC |= BIT2;
DSP_CORDIC_THETA = angle_q_1_15;
result.hSin = DSP_CORDIC_SIN;
result.hCos = DSP_CORDIC_COS;
return result;
}
使用CMSIS DSP计算sine与cosine值
CMSIS DSP是ARM公司的软件DSP库, 根据测试其计算性能与硬件DSP相差无几, 但是显然无异步模式, 它用的Q格式与DSP的Q格式稍稍有些差别(0-0x7fff表示2个.
生成360个点的Q15格式的Python脚本: for i in range(360):
print(int(i*32768/360), end=',')
得到一个360点的数组, 对应0到2π的弧度范围: const int16_t angle_array_360_0_2Pi[] = {
//数组内容请参考压缩包
};
CMSIS DSP计算函数, sine和cosine分别计算:
for (uint32_t idx = 0; idx < TEST_POINT_NUM; ++idx) {
volatile q15_t result_q15[2];
volatile float32_t result_f32[2];
q15_t angle_q1_15 = angle_array_360_0_2Pi[idx];
result_q15[0] = arm_sin_q15(angle_q1_15);
result_q15[1] = arm_cos_q15(angle_q1_15);
}
纯软件计算sine/cosineCortex M0是没有FPU的, 所以调用math头文件中的sin,cos函数都是使用标准软件浮点库运算, 作为比较, 也放在一起进行benchmark.
生成360个测试点的python脚本:
for i in range(360):
print('%.3f' % (i*math.pi/180), end=',')
得到一个360点的数组, 对应0到2π的弧度范围: const float32_t angle_array_360_0_2Pi_f32[] = {
单精度:
for (uint32_t idx = 0; idx < TEST_POINT_NUM; ++idx) {
volatile float32_t sin_vlaue_f32;
volatile float32_t cos_vlaue_f32;
float32_t angle_f = angle_array_360_0_2Pi_f32[idx];
sin_vlaue_f32 = sinf(angle_f);
cos_vlaue_f32 = cosf(angle_f);
}
双精度:
for (uint32_t idx = 0; idx < TEST_POINT_NUM; ++idx) {
volatile float64_t sin_vlaue_f64;
volatile float64_t cos_vlaue_f64;
float64_t angle_f64 = (double)angle_array_360_0_2Pi_f32[idx];
sin_vlaue_f64 = sin(angle_f64);
cos_vlaue_f64 = cos(angle_f64);
}
最终benchmark结果
benchmark | DSP | CMSIS DSP | float | double | V5 -O3 -Otime Stdlib | 222 | 312 | 6456 | 24037 | V5 -O3 -Otime Microlib | 222 | 312 | 8060 | 59873 | V6 -Ofast Stdlib | 202 | 330 | 6454 | 24021 |
简单解读下, 硬件DSP计算性能比起CMSIS DSP性能貌似强不了特别多, 但是CMSIS DSP会显著增加代码尺寸. 而且DSP有异步模式. 不管是硬件DSP还是CMSIS DSP受编译器/LibC库函数影响不大, 这也是预期中的.
当使用microlib时, 软件浮点库性能会下降, 尤其是双精度. 这是时间换空间的预期结果.
结论:
1. 如果可以使用定点模式计算, 尽量使用定点模式, 不管是硬件DSP还是CMSIS DSP比浮点快太多.
2. 如果一定要使用浮点, 尽量使用单精度.
3. 如果不是flash空间受限, 尽量不要用MicroLib.
准备还写一篇DSP单独运行的测试.
代码下载地址点这里.
|