2014-11-24 93 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,然後問題就解決了。