[信息] 使用STM32N6测试Helium指令

[复制链接]
217|0
STM新闻官 发表于 2025-11-1 19:42 | 显示全部楼层 |阅读模式
1. 简介
最近在给客户评估STM32N6上执行2048点FIR需要多长时间的事情。STM32N6是一颗高性能MCU,主频能达到800MHz,使用了Cortex-M55内核,对比Cortex-M7内核的一个特点是使用了ARMv8-M的指令集,支持Helium架构。本文将简单介绍MVE指令集,另外将对比测试普通情况下的FIR和使用MVE指令后的FIR执行时间。

2. Helium简介
ARM的指令对于向量化运算的支持在Cortex-A中就已经存在了,类似于NEON指令集。Helium是针对Cortex-M内核的向量化运算支持。SIMD(Single Instruction, Multiple Data)指令集用于Cortex-M系列。在ARMv8-M架构文档中,这些指令集也被称为MVE(M-Profile Vector Extension)指令。 MVE扩展重用了FPU浮点单元中的寄存器作为向量寄存器,每个向量寄存器128位,分为4个32位block,每一个block被称为一个beat,Cortex-M55是Helium架构中的双beats实现。意味着每个时钟周期会有两个beats数据,由于overlapping的存在,Cortex-M55相对于Cortex-M4和Cortex-M7会有约4倍性能的提升。


751596905f0d3b118e.png

上图中 ,1,2,3,4分别为不同时钟周期,每个时钟周期可以处理两个beats数据,即64位,在第二个时钟周期,由于VLDR指令和VMLA指令overlapping,即内核可以同时执行加载和处理指令,如果指令的pipeline和调度被设计的很合理的话,性能会有非常大的提升。

另外,Helium和FPU在Cortex-M55中是可选配的,并不是所有的Cortex-M55内核的MCU 都支持MVE 和FPU,MVE 又分为MVE-I(向量化整型和定点),MVE-F(向量化浮点),STM32N6对于Helium(MVE-F)和FPU均支持。 3. 使用NUCLEO-N657X0-Q测试FIR 我们接下来将使用Helium 指令进行 FIR 的基本测试,对比测试使用 Helium 指令后的结果,以及最快多久可以执行完2048个点的FIR,测试中使用了STM32N6 Nucleo开发板。

3.1. 主要测试函数

307546905f0f57225e.png

SinWaveX函数,用于计算正弦波形数据并存储到缓冲区中,其中: • _SSinX 是一个结构体,包含 Alpha, Yn_1, Yn_2, 和 Gain 等成员。 • buffer 是一个浮点数组,用于存储计算结果。 • len 是数组的长度。 可以看到汇编代码中生成了VLDR,VMUL等向量化指令,但他不属于Helium指令集,而是属于 ARM 的浮点和向量指令集,在ARMv7版本中引入。

7976905f10b722a2.png

上面这个FIR函数,实现了一个简单的FIR滤波器,其中:


• out: 输出数组,用于存储滤波后的信号。 • signal: 输入信号数组。 • cattable: 滤波器系数数组。 • len: 输入信号的长度。 • nfir: 滤波器系数的数量。 主要计算过程如下: 1. 初始化指针: p1 指向输入信号,p3 指向滤波器系数。 2. 外层循环: 遍历输入信号的每个样本。 3. 内层循环: 对每个样本进行滤波计算。 o p2 指向当前样本,ptable 指向滤波器系数。 o 计算 ftmp,即当前样本的滤波结果。 4. 存储结果: 将滤波结果存储到输出数组中。

853246905f12c57849.png

这段测试代码主要功能如下: • 该函数用于测试和验证 FIR 滤波器的功能。 • 它通过生成正弦波数据、复制数据、执行滤波操作来处理信号。 • GPIO 引脚的切换用于指示程序的运行状态。 • 无限循环确保滤波操作持续进行。 3.2. 验证主频 为了确保STM32N6工作在最高主频800MHz,还需要进行一些修改和测试。 测试方法是将主频16分频后,通过PA8引脚输出出来,800M/16=50MHz,也就是说应当在PA8管脚测量到50MHz的波形。


代码初始化: HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSA, RCC_MCODIV_16); 为了让STM32N6工作在800MHz,还需要确保VDDCORE供电电压为0.89V。Nucleo板上使用外部SMPS对VDDCORE进行供电,默认为0.81V,可以通过I2C改变供电电压为0.89V,参考代码为: BSP_I2C2_Init(); BSP_I2C2_WriteReg(0x92, 0x01, 0x64, 1); PA8脚测试结果如下:

452006905f14da9902.png

3.3. 使能Helium

700746905f163594d5.png

在IAR编译器中需要勾选上图的选项才可以使能Helium指令,如果是ARM编译器,需要设置以下参数: • cpu0.enable_helium_extension=1 • cpu0.vfp-present=1 • cpu0.vfp-enable_at_reset=1

3.4. 测试结果
3.4.1. 测试Case1:运行在SRAM2

275466905f17c04cbd.png

3.4.2. 测试Case2:运行在DTCM&ITCM

637796905f18dea3fa.png

3.4.3. 测试Case3:运行在DTCM&ITCM+Helium

590116905f1a46c871.png

180896905f1b164775.png

可以看到使用MVE指令集后运行速度进一步提升,比之前不使用时快约3倍,如果是16位浮点或定点,速度能快更多,达到10倍以上,以上代码区别在于重新使用了新的FIR函数,新的FIR函数来自ARM提供的官方函数arm_fir_f32,该函数使用MVE指令集大大优化了FIR过程。

667336905f1cd78fab.png

上图左侧中的do{} while()循环中,可以看到pTempDest和pTempSrc都是float32类型的指针,且每次加四,即vstrwq_p_f32这个函数每次可以处理4个float32单位的数据。 这段代码使用 ARM MVE 指令集来高效地处理浮点数据。它通过一个循环将源数组中的数据复制到目标数组中,使用谓词寄存器控制向量操作的有效性。每次循环处理 4 个浮点数,然后更新指针和计数器,直到所有元素都被处理完。 从右侧的汇编窗口可以看到使用了VLDRW.32, VMUL.F32, VFMA.F32等汇编指令,其中: VLDRW.32 Q0, [R1]: V表示这是一条Helium指令,W表示按字进行操作,32表示位宽。目标为128位寄存器Q0,源地址为R1指向的地址。所以该条指令用于从R1指向的地址加载4个32位宽的字到Q0寄存器。  对于其他指令,本文不再一一介绍,有关是Helium指令的更多详细内容建议参考ARM官方手册。


3.4.4. 测试总结

659506905f1f15abed.png

从测试结果来看,在其他条件都一致的情况下,代码运行在ITCM/DTCM内,比SRAM中要快6~7倍,使用Helium后要快3倍,基本符合预期。 4. 总结 Helium架构大大增强了Cortex-M55并行运算能力,在DSP运算方面大有可为。ARM官方的DSP库也集成了对MVE指令的支持,用户可以用官方库完成Helium的集成,对于其他并行的运算,用户也可以自己通过调用ARM的API完成并行运算,比如一些for循环的优化,可以通过MVE指令来加速。 除了工程师自己将代码并行化处理以外,还可以自动进行向量化,目前ARM的AC6编译器,对于自动向量化这一部分有很好的支持,工程师在Keil的编译器中只需要将优化等级设置为-O2及以上,Keil就默认使能自动向量化来优化代码。 另外,对于神经网络加速,Helium也提供了很好的支持,在CMSIS-NN库中已经集成了这部分,用户可以直接使用,本文不再介绍,感兴趣的工程师可以参考ARM官方文档。

424996905f211a8d44.png

文档中所用到的工具及版本 IAR : 9.60.3

412606905f222e90b7.png



您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:您的嵌入式应用将得益于意法半导体领先的产品架构、技术、多源产地和全方位支持。意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器。

1428

主题

1758

帖子

25

粉丝
快速回复 在线客服 返回列表 返回顶部