簡體   English   中英

未對齊訪問導致 ARM Cortex-M4 出錯

[英]Unaligned access causes error on ARM Cortex-M4

我有一個 object,它的地址不是 4 字節對齊的。 當存在保存 2 個寄存器的 STR 指令時,這會導致 cpu 出現 HardFault 錯誤。

這是生成的代碼:

   00000000 <_ZN8BaseAreaC1EPcmm>:
   0:   b510            push    {r4, lr}
   2:   4604            mov     r4, r0
   4:   6042            str     r2, [r0, #4]
   6:   e9c4 3102       strd    r3, r1, [r4, #8]
   a:   2001            movs    r0, #1
   c:   7420            strb    r0, [r4, #16]
   e:   b921            cbnz    r1, 1a <_ZN8BaseAreaC1EPcmm+0x1a>

這些是在“4: 6042...”行時的寄存器

R0   08738B82  R8          0  
R1   08738BAE  R9          0  
R2          0  R10  082723E0  
R3       2FCC  R11         0  
R4   08738B82  R12         0  
R5   20007630  R13  2000CB38  

如所見,STR 指令的目標寄存器未按 4 字節對齊。 指令STR r2, [r0, #4]執行良好。 但它會在下一個STRD r3, r1, [r4, #8]上發生硬故障。 如果我手動將寄存器 R4 更改為08738B80 ,它不會出現硬故障。

這是生成上述 asm 的 C++ 代碼:

BaseArea::BaseArea(char * const pAddress, unsigned long startOffset, unsigned long endOffset) : 
m_pAddress(pAddress), m_start(startOffset), m_end(endOffset), m_eAreaType(BASE_AREA) {

m_start是 class 中的第一個變量,與this具有相同的地址( 0x08738B82 ), m_end0x08738B86之后。

如何使 object 在 4 字節上對齊? 有人對此有其他解決方案嗎?

在基於ARM的系統上,您經常無法處理未與4字節邊界對齊的32位字(正如您的錯誤告訴您的那樣)。 在x86上,您可以訪問非對齊數據,但性能會受到很大影響。 如果ARM部件支持未對齊訪問(例如,單字正常負載),則存在性能損失, 並且應該存在可配置的異常陷阱。

ARM上的邊界錯誤示例( 此處 ),TLDR:存儲指向unsigned char的指針,然后嘗試將其轉換為double * (雙指針)。

要解決您的問題,您需要請求一個4字節對齊的內存塊並復制非對齊字節+用垃圾字節填充它以確保它是4字節對齊的(因此手動執行數據結構對齊)。 然后,您可以將該對象從其新地址解釋為4字節對齊。

來自TurboJ的評論中,顯式錯誤:

默認情況下,Cortex-M3和M4允許未對齊訪問。 但是他們不允許使用STRD指令進行無法訪問,因此就是錯誤。

你也可以發現它有助於看看對ARM迫使數據結構對齊。

以下情況至少適用於ARM體系結構(在cortex M0上驗證):

使用加載和存儲指令時,我們訪問的內存必須能夠被我們嘗試從內存訪問/到內存的字節數整除,否則我們將獲得硬故障異常。

例如:

LDR r0, = 0x1001
LDR r1, [r0]

上面代碼中的第二行將給出硬錯誤,因為它試圖讀取4個字節,但內存地址不能被4整除

如果我們將上面代碼中的第二行更改為以下內容

LDRB r1, [r0]; //從地址加載1個字節

上面的行不會產生硬故障,因為我們試圖訪問1個字節(可以從任何內存位置訪問1個字節)

另請注意以下示例;

LDR r0,= 0x1002
LDRH r1,[r0];   //Load half word from 0x1002

上述行不會產生硬故障,因為內存訪問是2個字節,地址可以被2整除。

正如您所發現的,Cortex-M4 支持 4 字節未對齊訪問,但不支持 8 字節未對齊訪問。 后者在 UFSR.UNALIGNED 位的文檔中有解釋:

UNALIGNED - 表示發生了未對齊的訪問操作。 未對齊的多字訪問,例如訪問非 8 字節對齊的uint64_t ,將始終生成此錯誤。 除了 Cortex-M0 MCU 之外,4 字節以下的未對齊訪問是否產生故障也是可配置的。

8 字節訪問可以是 STR 指令(如您的示例所示)或只是訪問uint64_t

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM