项目中遇到这样一段代码:

i2c_msg_s msg[2];
uint8_t tx[2][32]={0};
uint8_t rx[32]={0};

当执行到rx[32]={0}时,CPU进入TRAP,提示undefined instruction,该代码运行环境为arm cortex-A5,gcc编译。

调出汇编代码

	i2c_msg_s msg[2];
	uint8_t tx[2][32]={0};
400078f8:	e28d5020 	add	r5, sp, #32
400078fc:	e3a02040 	mov	r2, #64	; 0x40
40007900:	e3a01000 	mov	r1, #0
40007904:	e1a00005 	mov	r0, r5
40007908:	eb0061ad 	bl	4001ffc4 <memset>
	uint8_t rx[32]={0};
4000790c:	e3a04000 	mov	r4, #0
40007910:	e58d4000 	str	r4, [sp]
40007914:	f2c00010 	vmov.i32	d16, #0	; 0x00000000
40007918:	edcd0b01 	vstr	d16, [sp, #4]
4000791c:	edcd0b03 	vstr	d16, [sp, #12]
40007920:	edcd0b05 	vstr	d16, [sp, #20]
40007924:	edcd0b06 	vstr	d16, [sp, #24]

代码中初始化tx[2][32]中调用memset,但是初始化rx[32]时用的vmov指令。

这两个变量初始化方式不同,memset使用很多次,不会产生undefined instruction,那是否CPU不识别vmov指令呢。未验证该猜测,不初始化该变量重新编译

	uint8_t tx[2][32]={0};
400078f8:	e28d5020 	add	r5, sp, #32
400078fc:	e3a02040 	mov	r2, #64	; 0x40
40007900:	e3a01000 	mov	r1, #0
40007904:	e1a00005 	mov	r0, r5
40007908:	eb0061a7 	bl	4001ffac <memset>
	uint8_t rx[32];
	int i =0;

代码执行,没有报错。确定是vmov指令的问题。

由于vmov是NEON的扩展指令,该CPU可能不支持NEON加速,查询手册得知,该CPU不支持硬件浮点运算,故而也不会特别的去支持NEON。

查看编译选项,其中-mfloat-abi=softfp,编译中也没有开启NEON。

通过查询,找到如下描述:

 出于历史原因,GCC 只在被明确告知可以安全使用浮点和 NEON 指令时才会使用这些指令。在此进行控制的选项有些令人混淆,选项的一部分也可更改编译器所遵守的 ABI。-mfloat-abi 选项有三种可能的选项:
 
-mfloat-abi=soft -- 忽略所有 FPU 和 NEON 指令,仅使用核心寄存器集并利用库调用模拟所有浮点运算。
-mfloat-abi=softfp -- 使用与 -float-abi=soft 相同的调用规则,但会在适用情况下使用浮点和 NEON 指令。此选项为二进制,与 -mfloat-abi=soft 兼容,并且可以用于提高必须遵循软浮点环境的代码的性能,但需要是已知相关硬件指令也可用的环境。
-mfloat-abi=hard -- 在适用情况下使用浮点和 NEON 指令,并且还更改ABI 调用规则以便生成更高效的函数调用;现在可以在扩展寄存器中的函数之间传递浮点和矢量类型,不仅节约大量复制操作,而且也意味着需要在堆栈上传递参数的调用变少。

ARM Cortex-A 处理器和GCC 命令行-EDA365

改成-mfloat-abi=soft,汇编中没有出现vmov指令。

Logo

加入社区!打开量化的大门,首批课程上线啦!

更多推荐