2014-11-24 64 views
2

当我运行我的程序,这只是计算正弦波:的ARM Cortex M4硬故障 - 浮点

for(i = 0; i < ADS1299_SIGNAL_WINDOW; i++){ 
    TEST[i] = (float32_t)(10.0f * (float32_t)(arm_sin_f32((float32_t)(3.14f * i/ADS1299_SIGNAL_WINDOW)))); 
} 

编译器会生成以下行,这会导致硬件故障:

800702a: ed2d 8b04  vpush {d8-d9} 

发生了什么?作为参考,这里是我的标志编译器:

SETTINGS="-g -nostartfiles -mthumb -mthumb-interwork -march=armv7e-m -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -fdata-sections -ffunction-sections -O3 -Wl,-T,../STM32F407VG_FLASH.ld" 
DECLARE="-DARM_MATH_CM4 -D__FPU_PRESENT=1 -D__FPU_USED" 
.... -larm_cortexM4lf_math 
+0

是的。我忘了提及我正在使用STM32F407芯片。抱歉! – SolarSunrise 2014-11-24 23:27:36

+0

是的,这是没有任何操作系统的裸机。上面的代码直接在主要的。 FPU在主开始处启用(SCB-> CPACR | =(0x3 << 10 * 2 | 0x3 << 11 * 2)。 – SolarSunrise 2014-11-24 23:35:16

+1

这将有助于包含[您的完整代码](http:// stackoverflow。 com/help/mcve) - 这很难说明上电和违规指令之间是什么和不发生什么,我认为这很重要 – Notlikethat 2014-11-24 23:58:14

回答

3

的问题是,你正在做两个CPACR启用,在同一范围内的一些浮点运算。由于main中的代码使用浮点寄存器,所以编译器(运行良好并遵守ABI)将发出代码以保留那些进入main的寄存器。 之前执行main中的任何其他代码。包括写入CAPCR使其可访问。哎呀。

为了避免这种情况,之前进入主在复位处理程序在CPACR 使FP(如果你的工具链允许的话),或者干脆全部FP操作的另一个功能,并确保main本身不触及任何FP寄存器。

这也将是明智的(如果您还没有),以确保您在CPACR写入后有一个DSB; ISB同步序列。否则,您可能仍然会从管道中已有的任何陈旧的FP设备中获得故障。

+0

奇怪的是,当我删除标志时: “-fsingle-precision-constant”,问题就消失了,但是添加另一段代码后,问题再次出现,我会尝试打开CPACR,然后像你所建议的那样打开,希望能够解决问题 – SolarSunrise 2014-11-26 10:21:21

+0

@SolarSunrise它的_possible_这个变化使得寄存器分配器碰巧从临时/变量寄存器'd0'-'d7'中选择,意味着它不会在启用之前发出代码来保存它们。比较拆卸可能是有启发性的,但正如你所看到的,它不是那种类型的你可以依靠。 – Notlikethat 2014-11-26 11:33:20

+0

原来,根据反汇编输出,在FPU初始化例程之前调用有问题的指令。在主功能解决问题之前启用FPU。谢谢!你刚刚从另一个10小时的调试中拯救了我... – SolarSunrise 2014-11-27 16:10:54

0

如果使用FPU,堆栈应该对齐到8个字节的边界。如果您正在使用RTOS,请检查线程堆栈初始化代码。如果您使用裸机运行,请检查堆栈设置的启动代码。

1

我认为问题在于FPU未启用。我有同样的问题与凯尔  4.北欧半导体SDK的例子在Keil IDE为FPU的复选框启用标记,但在SystemInit代码是有条件编译如下:

void SystemInit(void) { 
#if (__FPU_USED == 1) 
    SCB->CPACR |= (3UL << 20) | (3UL << 22); 
    __DSB(); 
    __ISB(); 
#endif 
} 

但我认为Keil   4 IDE不会将此__FPU_USED设置为1,并且在VPUSH指令中我有一个HardFault,因为FPU未启用。

我认为你需要在SystemInit中启用FPU,然后问题就解决了。