曾有STM32用戶反饋,他發(fā)現(xiàn)同樣代碼在STM32F1系列芯片上運行好好的,而且代碼跟STM32外設(shè)關(guān)聯(lián)性也不大。而當代碼運行在stm32L071VB單片機時,在做數(shù)據(jù)的內(nèi)存拷貝時會進入硬件錯誤【Hard Fault】,覺得不可理解。
它定義了類似下面的數(shù)據(jù)結(jié)構(gòu),并用到預(yù)編譯命令安排結(jié)構(gòu)體數(shù)據(jù)成員的存放對齊原則:
#pragma pack? (1)
Struct Comm_Frame {
uint8_t Head;
uint16_t Data[3];
uint8_t Class;
uint16_t Tail [2];
} Stream;
#pragma pack ()
他使用到基于上面結(jié)構(gòu)體定義的數(shù)據(jù)變量進行數(shù)據(jù)通信,為了讓數(shù)據(jù)成員在內(nèi)存中緊湊連續(xù)存放,將數(shù)據(jù)結(jié)構(gòu)體的地址對齊規(guī)則指定為字節(jié)對齊,即使用#pragma pack (1)。數(shù)據(jù)在內(nèi)存中像下面樣子擺放:
他這樣設(shè)計的話,數(shù)據(jù)結(jié)構(gòu)體中的Data[]和Tail[]雙字節(jié)數(shù)據(jù)會出現(xiàn)在奇數(shù)地址的地方。那么,當將上述Stream.Data[]數(shù)據(jù)拷貝出去的時候,在基于雙字節(jié)數(shù)據(jù)類型的指針尋址訪問時,會出現(xiàn)被訪問數(shù)據(jù)的地址不遵循2倍數(shù)的原則,即出現(xiàn)訪問地址不對齊的問題,可能導(dǎo)致運行出錯。一般來講,對于ARM內(nèi)核的芯片,基于雙字節(jié)數(shù)據(jù)寬度的尋址訪問時,被訪問數(shù)據(jù)的地址要求是2的倍數(shù);基于4字節(jié)數(shù)據(jù)寬度的尋址訪問時,地址要求是4的倍數(shù)。
比如:這里定義了一個數(shù)組uint16_t forcomp[3]和下面兩個指針:
uint16_t *pointer1 = &forcomp[0];
uint16_t *pointer2 = &Stream.Data[0];
現(xiàn)將上面結(jié)構(gòu)體成員Stream.Data[]的內(nèi)容通過指針尋址按如下方式拷貝進?forcomp[]?。
上面的代碼如果運行在基于M0或M0+內(nèi)核的STM32芯片的話,就會出現(xiàn)Hard Fault錯誤. 客戶使用的芯片stm32L071VBT6正是基于M0+內(nèi)核的STM32芯片。
為什么會這樣呢?這可以從Cortex M0/M0+的內(nèi)核技術(shù)手冊上看到相關(guān)描述:
顯然,基于M0、M0+內(nèi)核的芯片,它是不支持非對齊尋址訪問的。
客戶又說過,相同代碼在STM32F1芯片上運行又沒有問題,那怎么解釋呢?
STM32F1系列MCU是基于ARMCortex M3內(nèi)核的芯片,關(guān)于地址對齊方面跟M0/M0+有所不同。M3內(nèi)核支持部分指令的非對齊地址訪問,相關(guān)描述如下:
也就是說,基于CortexM3內(nèi)核的芯片,它支持部分指令的非對齊訪問,但非對齊訪問要慢于對齊訪問。即非對齊訪問是需要代價的,訪問效率會受到影響。所以,我們在應(yīng)用中要盡量遵循地址對齊的尋址訪問方式。關(guān)于地址對齊話題,在各個ARM內(nèi)核技術(shù)參考手冊里略有介紹。
結(jié)合本案的實際情況,碰巧用戶代碼先是可以正常運行于基于M3內(nèi)核的STM32F1芯片,而在基于M0+內(nèi)核的芯片上出現(xiàn)了異常。導(dǎo)致他覺得不好理解。
這里,指針所指數(shù)據(jù)類型為雙字節(jié)類型,為了避免在M0/M0+內(nèi)核芯片里尋址訪問時發(fā)生非對齊而導(dǎo)致的異常,可以將結(jié)構(gòu)體變量的內(nèi)存地址對齊方式改為雙字節(jié)對齊,即使用#pragma pack (2)。數(shù)據(jù)在內(nèi)存中像下面這樣擺放。
這樣修改后,經(jīng)過測試的確沒有問題。結(jié)合到客戶的具體情況,客戶希望數(shù)據(jù)連續(xù)、緊湊存放,不希望數(shù)據(jù)間有空隙,即結(jié)構(gòu)體數(shù)據(jù)成員的內(nèi)存地址對齊規(guī)則不變,仍然采用pack(1)。那么,數(shù)據(jù)拷貝操作時可以將雙字節(jié)數(shù)據(jù)類型的指針強轉(zhuǎn)為單字節(jié)數(shù)據(jù)類型的指針,將雙字節(jié)數(shù)據(jù)按字節(jié)對齊尋址方式分作兩次連續(xù)讀取完成。此時,用戶只需將應(yīng)用程序稍作調(diào)整即可。
所以,在STM32開發(fā)過程中,有些代碼或許跟MCU外設(shè)沒什么關(guān)系,但可能跟內(nèi)核有關(guān)。STM32系列眾多,涉及多個ARM內(nèi)核,不同的內(nèi)核在諸多方面存在些差異,這點需要注意。其實,從MCU軟件開發(fā)層面來看,地址對齊問題、中斷優(yōu)先級安排問題、堆棧安排問題,都是些比較隱蔽的問題,出錯了后果往往也很嚴重,我們平時可以多留意下。
-
STM32
+關(guān)注
關(guān)注
2264文章
10858瀏覽量
354385 -
代碼
+關(guān)注
關(guān)注
30文章
4726瀏覽量
68248 -
數(shù)據(jù)結(jié)構(gòu)
+關(guān)注
關(guān)注
3文章
569瀏覽量
40076
原文標題:一個跟地址對齊有關(guān)的應(yīng)用異常案例
文章出處:【微信號:stmcu832,微信公眾號:茶話MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論