一個對齊的問題

最近碰到一個問題,有個程序是跑在ARM cortex M4上。 之前用-O0編譯的時候運行一切正常, 但用-O3編譯就會有unaligned的UsageFault。但因爲空間的問題又必須用-O3編譯。

問題的原因

跟蹤調試了一些,出問題的是下面的代碼:

uint32_t *txb = (uint32_t*)buf;
while (len) {
	uint32_t data = *txb++;//UsageFault
    reg_write(addr, data);
    ...
}

而這裏的buf本來是一個uint8的指針,並且因爲上層傳輸協議的原因,地址並不是4字節對齊的。在用-O0編譯的時候,彙編代碼如下:

LDR r0,[r11],#04
STR r0,[sp.#0x10]

其中LDR/STR 這一系列的指令是可以用unaligned的地址的,只是速度會變慢。

如果用-O3編譯,彙編代碼就變成這樣:

LDM r0!,{r2}
STR r2,{r8,0x60}

編譯器認爲LDM指令更加高效,替換了LDR指令。 但LDM/STM/LDRD/STRD這幾個指令不支持unaligned的訪問,所以一定會有UsageFault。

問題的預防

我們可以設置UNALIGN_TRP, 這樣即使使用LDR指令,如果有unaligned的訪問也會有UsageFault。這用就可以發現代碼中的非對齊的問題。

SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章