2026 / 07 / 22
RA8 Cortex-M85 Helium入门指南
瑞萨电子在2023年10月底推出强大的RA8系列MCU,具备突破性的3000 CoreMark,并可满足客户应用所需的完全确定性、低延迟及实时操作要求。RA8系列MCU同时也是业界首款采用Arm® Cortex®-M85处理器的产品,能够提供卓越的6.39 CoreMark/MHz性能——这一性能水平将使系统设计人员能够使用RA MCU替代应用中常用的微处理器(MPU)。全新系列产品是广受欢迎的基于Arm Cortex-M处理器的RA产品家族中的一员。此外,为其它RA产品构建的现有设计可以轻松移植到新型RA8 MCU上。
新型RA8系列MCU部署了Arm Helium™技术,即Arm的M型矢量扩展单元(M-profile Vector Extension——MVE)。MVE是ARM v8.1M架构中非常重要的一部分。目前ARM v8.1M架构下的内核包括Cortex®-M52、Cortex®-M55、Cortex®-M85三种。下面的表格Arm Cortex-M Processor Comparison Table详细展示了从Arm®v6到Arm®v8.1M内核之间的不同。可以容易地发现,Cortex®-M85是目前性能最强的Arm® Cortex®-M内核MCU。

您可点击链接获取该表格原文:
Arm Cortex-M Processor Comparison Table:https://armkeil.blob.core.windows.net/developer/Files/pdf/product-brief/arm-cortex-m-processor-comparison-table.pdf
Arm v8.1-M架构是Arm v8-M架构的扩展版本。除了新的矢量指令集架构(Helium)以外,还有几个其他新特性:
-
循环和分支增强的附加指令集(低开销分支扩展,Low Overhead Branch Extension)。
-
支持半精度浮点指令。
-
调试功能增强,包括性能监测单元(Performance Monitoring Unit,PMU)和针对信号处理应用程序开发的调试附加功能支持。
-
用于FPU的TrustZone管理增强指令集。
-
非特权调试扩展。
-
内存保护单元(Memory Protection Unit,MPU)提供了一个新的内存属性,即“特权模式下永不执行”(Privileged eXecute Never,PXN)的属性。这允许当CPU处于特权模式下时阻止执行任意代码,而这些代码可能已经写入了用户空间。这是一个重要的安全特性。
-
可靠性、可用性及可维护性(Reliability,Availability and Serviceability,RAS)扩展。
引入Helium是为了在Cortex®-M内核MCU上实现更高效的DSP类和机器学习操作。它和Cortex®-A内核MPU中Neon有很多相似之处。Neon和Helium都使用FPU中的寄存器作为矢量寄存器。两者都使用128位向量,并且许多向量处理指令对于两种体系结构都是通用的。然而,Helium是一种全新的设计,可在小型处理器中实现高效的信号处理性能。它为嵌入式用例提供了许多新的架构功能,因为它针对面积(成本)和功耗进行了优化,为M-Profile架构带来了类似Neon的功能(Cortex-A的SIMD注指令)。Helium经过优化,可有效利用较小Cortex-M内核中的所有可用硬件。下表详细给出了Helium和Neon之间的对比信息。

目前有许多系统将Cortex-M处理器和专用可编程的DSP处理器结合来使用。Helium允许这样的系统只用一个处理器来实现。这样做有如下优点:
-
从软件开发的角度来看,它允许使用单个工具链,而不是分别对CPU和DSP使用各自的编译器和调试器。这就意味着程序员只需要熟悉一种架构。
-
消除了对处理器间通信的需求,这点可能非常重要,因为要对实时交互的两个运行时处理器中的不同软件进行调试既困难也耗时。
-
Cortex-M系列的CPU相比专用DSP而言,更易于编程。
-
在硬件设计层面,使用一个处理器(而不是两个处理器)可以简化系统,从而减少芯片面积和成本,并缩短开发周期。
在详细介绍Helium之前,我们现在来聊聊标量和矢量的概念。
数学和物理世界中的观点
计算机科学世界中的观点
- 通常用来处理通用的计算任务,如文字处理和电子表格。
- 功耗低,价格便宜。
- 对于图像,视频,音频数据处理等需要并行处理大量数据的任务特别有用。
- 也可用于科学计算,加速复杂算法的处理。
- 功耗高,价格稍高。
Helium寄存器、数据类型和通道
Helium寄存器是128位的,一共有8个Helium寄存器,寄存器数量不可修改。它和浮点单元(FPU)共同使用。在FPU中使用S0~S31来访问32个单精度(32位)寄存器,同样的硬件寄存器也可看做16个双精度(64位)寄存器D0~D15。例如,D0和S0、S1共用64位相同的硬件寄存器。在Helium架构中,Helium使用8个矢量寄存器Q0~Q7。这就意味着,Helium寄存器Q0和S0~S3、D0~D1浮点寄存器使用相同的物理寄存器,Q1和S4~S7、D2~D3浮点寄存器使用相同的物理寄存器,其他Helium寄存器以此类推。因为Helium寄存器重用了标量FPU寄存器,所以当发生异常时无须使用额外的资源去保存和恢复这些寄存器(同样不影响中断延迟)。

每个Helium寄存器都可以划分为8位,16位,32位宽的通道。每个通道可以被一条指令看作:
-
整型数值(8/16/32位宽)
-
定点饱和值(Q7/Q15/Q31)
-
浮点数值(半精度FP16/单精度FP32)

下图是一个矢量寄存器相加的示例。Helium寄存器q5和q0都是8个int16的元素数据(8个通道),将他们相加的结果存在q0中。

Helium允许矢量中的每个通道有条件地执行,这称作通道预测。矢量预测状态和控制寄存器(VPR)保存每个通道的条件值。某些矢量指令(比如矢量比较VCMP)可以改变VPR中的条件值,当这些条件值被设置好以后,接下来就可以使用VPT(矢量条件预测)指令,以每个通道为基础在矢量预测中实现条件执行。
Helium指令集
这里介绍的是Helium的汇编语言指令集,虽然大部分程序员不会直接使用这些指令,而是通过C语言或者高级语言编程实现,但是了解汇编语言指令集,可以有如下收获:
-
在优化C代码时,为了确定其是否被充分地矢量化,能够审视编译器的输出以及熟悉指令集是非常有帮助的。
-
当调试不能正常工作的代码时,通过阅读反汇编代码去理解每一行发生了什么,对于寻找代码的问题是非常有用的。
-
了解指令集可能有助于编写高效的代码,甚至节省功耗,尤其是在使用原语函数的情况下。
Helium指令结构和其他Cortex-M处理器中的VFP(浮点)指令结构是相似的。
Helium指令格式如下:

Helium指令都是以字母V开始的,然后跟着如下符号,符合中的{}是可选的,<>是必须出现的:
-
mod:指令修饰符,可能没有,也可能是Q(saturating)饱和,H(halving)减半,D(doubling)加倍,R(rounding)四舍五入中的一个。
-
op:具体操作,例如ADD(相加),SUB(相减),CMP(比较)等。
-
shape:有些指令中,可以选择性的指定L(long)或N(narrow),这是 “形态” 相关的修饰符。
- L:Long表示输入元素在操作前会被扩宽。1个8位的元素可能会被扩宽为16位或32位,或者1个16位元素被扩宽为32位。
- N:Narrow表示输入元素在操作前会被压缩。
-
extra:有些指令中的特定修饰符,可能是T(top),B(bottom),A(accumulate),X(exchange)或者V(across)中的一个。
-
cond:此处指定的条件仅适用于VPT(Predication)模块。可能是T(Then)或者E(Else)。
-
.dt:数据类型,可能是F(float)浮点,I(integer)整数,S(signed)有符号,U(unsigned)无符号。
-
dst:目标寄存器,可以是通用寄存器(R)或者矢量寄存器(Q)。
-
src:源寄存器,可以是通用寄存器(R)或者矢量寄存器(Q)。
-
rot:旋转,用于一些操作复数的指令。
VLDRW.U32 Q0, [R0]

该指令中的首字母是V,表示这是一条Helium(或是Neon,或者浮点)指令,LDR表示寄存器从内存加载内容,W表示按字大小操作,,,都为空,数据类型是U32,无符号32位整数。加载的目标是128位寄存器Q0(矢量寄存器),源是标量寄存器R0指向的内存地址。该指令表示将从R0存储的地址中加载4个32位宽的数据到Q0寄存器中。
Helium指令分类如下:

Helium编程方式
Helium编程方式目前来说,一共4种。
-
矢量库
-
自动矢量化
-
原语函数(intrinsics)编程
-
汇编指令编程
矢量库
目前,ARM CMSIS DSP和NN是已经对Helium优化好的Helium矢量库。使用矢量库来进行Helium编程,是最简单的方法。
-
CMSIS DSP是数字信号处理函数库,具有针对8位整数,16位整数,32位整数和32位浮点数的不同函数,提供了丰富的函数,包括基本数学函数,复数数学函数,滤波器函数,变换函数,矩阵操作函数,电机控制函数,插值函数,统计函数等。该库包含了这些函数的Helium优化版本,并不断更新迭代中。
-
CMSIS NN是神经网络函数库,以最小的内存开销针对Cortex-M处理器优化的软件内核,同样地,这些函数也可以利用Helium得到最优性能。
CMSIS矢量库中的函数代码有3个C预处理器定义来选择Helium版本。
#define ARM_MATH_HELIUM
#define ARM_MATH_MVEI //支持整型Helium
#define ARM_MATH_MVEF //支持浮点型Helium
比如CMSIS DSP中的 arm_clip_f32函数,可以看到该函数已经使用了Helium原语函数。

比如CMSIS NN中的arm_nn_lstm_update_cell_state_s16函数,可以看到该函数使用了Helium原语函数。

当使用矢量库的时候,不同编译器中的MVE设置


自动矢量化
自动矢量化就是编译器在C/C++代码中自动检测到可以使用Helium指令并执行优化的过程。优化后的代码在速度和尺寸方面可能与手工优化的汇编代码或包含原语函数的C代码一样高效,这只需要很少的时间去编写和调试代码,而且无须对目标微架构有详细了解。C代码也更有可移植性。
如下面的代码,这是一种很常见的普通写法,一个for循环里面做一些逻辑判断处理。

通过使用自动矢量化后的反汇编代码如下,红色框部分的代码里面已经出现了Helium的汇编指令。

自动矢量化和编译器的优化等级设置有关,当Arm Complier 6和LLVM编译器的优化等级为-O2或者更高时,自动矢量化默认使能,在MDK Arm Complier 6中可以使用“-fno-vectorize”选项可以禁止自动矢量化。当优化等级为-O1时,自动矢量化默认禁止,使用“-fvectorize”选项可以使能自动矢量化,当优化等级为-O0时,自动矢量化总是被禁止。其他编译器的行为可能不同,具体可以查阅对应的文档。
原语函数(intrinsics)编程
原语函数是允许利用Helium而不必直接编写汇编代码的一组C/C++函数。ACLE文档中包括Helium原语规范。目前最新的文档为mve-2021Q4。原语函数的实现包含在arm_mve.h文件中。函数包含简短的汇编语言部分,它们被内联到调用的代码中。
ACLE文档:https://github.com/ARM-software/acle/releases/tag/r2023Q2
使用原语函数有如下优点:
-
程序员能够直接访问Helium指令集,这允许编写充分优化的代码,利用所有Helium特性。
-
C/C++可用于大多数代码,只有当需要优化而矢量化C编译器无法执行优化时,才会使用Helium原语。这就意味着只有在必要时才使用底层代码。
-
相比于采用汇编语言编写的代码,含有Helium原语的C和C++代码可以移植到一个新的平台,仅需要少量修改,甚至无须修改。
-
使用原语避免了很多与直接使用汇编语言编码相关的难点。
完整的指令列表详见:https://developer.arm.com/architectures/instruction-sets/intrinsics/
原语函数中,Helium矢量数据类型名字模式如下所示,这在“arm_mve.h”中有详细定义和描述。
x_t
如:
uint8x16_t是一个描述16个无符号8位的矢量。
int16x8_t是一个描述8个16位的矢量。
float16x8_t是一个描述4个16位浮点数(半精度)的矢量。
float32x4_t是一个描述4个32位浮点数(单精度)的矢量。
注:Helium是128位寄存器,它的元素大小和通道总数相乘的结果只能是128,不能是64,也就是说,不支持int8x8_t/uint8x8_t/int16x4_t/uint16x4_t/float16x4_t/float32x2_t数据类型。这点和Neon是不同的。Neno可以支持64和128。
Helium矢量数组结构体类型如下:
可以发现,矢量数组结构体名字只比单个矢量数据类型多了一个length_of_array。它表示一共有几个helium寄存器组成,即helium寄存器的数量。在该结构体中,包含一个名为val的元素,此结构体类型映射Helium加载和存储操作访问的寄存器,Helium可以用一条指令加载/存储多达4个寄存器。结构定义示例如下:
struct int16x8x2_t
{
int16x8_t val[2];
};
此结构类型仅由加载、存储、转置、交织和去交织指令使用;要对实际数据执行操作,请从各个寄存器中选择元素。如:.val[0] 和.val[1]。
下图代码片段是使用原语函数进行矢量相乘的例子。

原语编程里面还涉及原语预测,原语尾部处理等知识,本处不在展开说明,详细信息可以访问arm官网查阅相关文档了解和学习。
汇编语言编程
在汇编代码中直接编写Helium指令是很没有必要的,通常只会在特殊的场景下才会这样做。即当编程人员可以比编译器更好地分配寄存器时,比如有太多重写变量和输入输出变量。
下图所示为复数矢量点积的汇编语言代码。

瑞萨RA8x1系列工具支持如下:

*编译器必须直接从第三方购买并获得许可
J-Link model需要支持Cortex-M85
- BASE / PLUS V11
- ULTRA+ / PRO V5
- J-Link Model更多信息,请参考:https://wiki.segger.com/J-Link_Model_Overview
瑞萨RA8x1编译器支持如下:

注:
1.CM85有限支持。
2.Beta版本。
3.IAR自动矢量化支持还在开发中。
PACBTI : Pointer Authentication Code & Branch Target Identification 指针验证和分支目标识别
Helium实例
我们将通过一个RGBA图像数据中的R(红色),G(绿色),B(蓝色)3种色彩通道数据分离的例子,介绍使用helium原语函数的解交织(deinterleaving)功能。
在计算机图形学中,一个RGB颜色模型是由RGB3个色彩通道数据构成的,每个通道用了8位色彩深度,共计24位,包含了所有的彩色信息。为实现图形的透明效果,采取在图形文件的处理与存储中附加上另一个8位信息的方法,这个附加的代表图形中各个素点透明度的通道信息就被叫做Alpha通道。Alpha通道使用8位二进制数,就可以表示256级灰度,即256级的透明度,因此图片可以是RGB888或者RGBA888,当然现在也有一些其他的格式,如RGB565,RGB555等。
下图这张彩色图片的分辨率是240*160,格式是RGBA8888的。

图片的色彩数据排列为按照下列方式,RGBA,RGBA,如此反复循环。

通过使用vld4q来进行4个色彩通道数据的解交织操作。

在这个例子中,我们使用了以下的Helium原语函数编程。

通过上面的代码,我们可以得到3张不同灰度的图片,下面仅给出G通道的数据供参考,其他通道数据类似,只是灰度不同。

图像数据可以使用e2 studio中的Memory工具直接显示出来,非常方便图像类的调试。

使用普通的标量操作C代码,如下所示:

在RA8x1的实际部署中,对比了上面的两种代码运行时间,使用了helium原语函数编程的代码比普通的标量C代码要快1倍以上。如果图片的分辨率越大,提示效果会更加明显。
相关参考资料
您可复制下方对应的链接到浏览器中打开查看:
102095_0100_00_en_HeliumProgrammersGuide_CodingForHelium.pdf
102107_0100_01_HeliumProgrammersGuide_NeonMigration.pdf
arm-helium-technology-ebook-v2.pdf
Arm Helium技术指南:Cortex-M系列处理器的矢量运算扩展
