為什么MISRA要求你不要使用位域-本文告訴你真相 (qq.com)
一.前言
做過嵌入式開發(fā)的一般會看到一條編程規(guī)范:”不要使用位域”,一般都是知其然不其所以然,了解的多一點(diǎn)的可能知道位域是實(shí)現(xiàn)相關(guān)不具備可移植性,那么繼續(xù)追問哪些行為是實(shí)現(xiàn)相關(guān)哪些行為導(dǎo)致移植性問題? 或者還有人知道,存儲布局,對齊等行為是實(shí)現(xiàn)相關(guān)會導(dǎo)致不可移植性。如果再追問位域產(chǎn)生的匯編代碼是什么樣的,怎么進(jìn)行讀-修改-寫操作的?知道這些內(nèi)容的就更加少之又少了。 讀寫肯定不能讀指定位數(shù),只能字節(jié),或者16位,32位這種,那么編譯器到底讀寫用什么寬度? 這時基本大部分人都不知道了。
知其然知其所以然,尤其是嵌入式開發(fā)和硬件結(jié)合比較緊密,所以一定要了解細(xì)節(jié),我們這一篇從一個問題引出然后去分析查找原因,只有遇到問題然后去分析解決它才會有更深刻的映像。
二.問題分析過程
問題是驅(qū)動程序中一個寄存器的某個位域修改,導(dǎo)致其他位域的值被修改了。
關(guān)鍵代碼如下,
1.typedefunionnfc_ena_union{
2. uint32_tw;
3. struct{
4. /*spienable,oncethespitransiscompleted,thisbitwillbeclearedbyHWautomaticlly*/
5. uint32_tnfc_ena:1; //[0]
6. uint32_treserved_0:3; //[1,3]
7. /*swrequesttousedp*/
8. uint32_tnfc_dp_req:1; //[4]
9. uint32_treserved_1:3; //[5,7]
10. /*duetodelayinreceivingdata,nfcdelayonebeattorx*/
11. uint32_tnfc_rx_delay_en:1; //[8]
12. uint32_treserved_2:7; //[9,15]
13. /*spitransdatalength,unitisbyte,oncethespitransiscompleted,thisbitwillbeclearedbyHWautomaticlly*/
14. uint32_tnfc_data_len:16; //[16,31]
15.}_b;
16.}nfc_ena_u;
1./**
2.*fnintnfc_set_datalen(uint8_tid,uint16_tlen)
3.*param[in]idportid
4.*param[in]lendatalen
5.*retval0ok
6.*retval<0?param?err
7.*
8.*/
9.NFC_INLINEintnfc_set_datalen(uint8_tid,uint16_tlen)
10.{
11. if(id>=HW_NFC_PORT_MAX)
12.{
13. return-1;
14.}
15.nfc_base[id]->nfc_ena._b.nfc_data_len=len;
16. return0;
17.}
執(zhí)行之前該寄存器值為0x00020100

nfc_base[id]->nfc_ena._b.nfc_data_len= len
匯編代碼被優(yōu)化為了寫高16位

執(zhí)行完后寄存器低16位變?yōu)榱?

這是因為寄存器硬件上只支持32位的寫操作,所以寫高16位導(dǎo)致低16位清零了,這是硬件決定的。
二.驗證
一般想到的就是優(yōu)化相關(guān),加volatile等,我們分別驗證下。
3.1不使能編譯器優(yōu)化
編譯器優(yōu)化選項改為”-O0”
代碼不變
依然會按照16位訪問,導(dǎo)致低16位被清掉。
所以可以看到這個和編譯器行為有關(guān),編譯器顯然不是根據(jù)優(yōu)化等級決定位域的操作寬度,這里而是根據(jù)位域的寬度剛好是16位對齊,所以優(yōu)化為了16位操作指令。


3.2使用volatile避免編譯器優(yōu)化
#ifndef__IOM
#define__IOM volatile
#endif
所有uint32_t替換為__IOM uint32_t
還是一樣的

顯然匯編代碼的訪問寬度也不受volatile影響。
3.3為什么指定了uint32_t和volatile還會優(yōu)化。
問題來了為什么告訴了編譯器是uint32_t和volatile,為什么其還要一意孤行,要優(yōu)化為16位訪問指令呢,答案就是因為是標(biāo)準(zhǔn)沒有規(guī)定,這是編譯器實(shí)現(xiàn)行為決定的,所以編譯器設(shè)計者決定的(當(dāng)然也會有一些現(xiàn)實(shí)考慮的),可能不同編譯器行為不同,這里以GCC為例。
GCC編譯器文檔中可以找到答案
GCC的文檔可以看到如下內(nèi)容,也給出了最好是不使用位域的原因


另外也介紹了位域哪些行為也是編譯器實(shí)現(xiàn)相關(guān)的,所以嵌入式可移植性考慮不要使用位域

那么有沒有辦法指定編譯按照一定大小訪問呢,GCC有編譯選項可以控制見下一節(jié)。
3.4使用編譯器選項-fstrict-volatile-bitfields

可以看到改為了sw指令,按照32位進(jìn)行了操作

四.一些廠家做法
如下可見
4.1CMSIS
core_cmxx.h中定義
CMSIS中進(jìn)行了定義,寄存器個別使用位域
1./*IOdefinitions(accessrestrictionstoperipheralregisters)*/
2./**
3.defgroupCMSIS_glob_defsCMSISGlobalDefines
4.
5.IOTypeQualifiersareused
6.litospecifytheaccesstoperipheralvariables.
7.liforautomaticgenerationofperipheralregisterdebuginformation.
8.*/
9.#ifdef__cplusplus
10.#define__Ivolatile/*!
4.2ST
1./**
2.*@briefUniversalSerialBusFullSpeedDevice
3.*/
4.
5.typedefstruct
6.{
7.__IOuint16_tEP0R;/*!
4.3瑞薩
__I,__O__ROM也是core_cmxx.h中定義,大量使用位域
1.#ifndef__IM/*!
五.總結(jié)
結(jié)論就是正如很多嵌入式編程規(guī)范所描述的(比如MISRA),一般不建議使用位域,因為涉及到位域的訪問,存儲等行為都是實(shí)現(xiàn)定義的,不具備可移植性。
嵌入式領(lǐng)域寄存器的定義也最好不要使用位域,到寄存器級別以寄存器操作為單位即可,每個寄存器都要使用__IM,__OM,__IOM描述。
如果一定要使用位域可以使用-fstrict-volatile-bitfields選項,使用GCC測試可以保證按照固定指定大小訪問,但是不保證其他編譯器也支持該選項,最好能不使用就不使用位域。
審核編輯黃宇
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
嵌入式
+關(guān)注
關(guān)注
5152
文章
19699
瀏覽量
317977
-
寄存器
+關(guān)注
關(guān)注
31
文章
5437
瀏覽量
124684
-
編譯器
+關(guān)注
關(guān)注
1
文章
1662
瀏覽量
50268
-
MISRA
+關(guān)注
關(guān)注
0
文章
22
瀏覽量
7232
-
嵌入式編程
+關(guān)注
關(guān)注
0
文章
27
瀏覽量
10563
發(fā)布評論請先 登錄
相關(guān)推薦
熱點(diǎn)推薦
電子硬件設(shè)計牛人張飛告訴你“11個不要”
我們不知道抄來的電路優(yōu)點(diǎn)在哪,缺點(diǎn)是什么。不要隨便的去抄別人的電路,一定要根據(jù)自己的知識來設(shè)計這樣一個電路。即使你看到別人電路時,你也要能夠分析和理解別人的電路,把電路中的問題找出來,然后變成
發(fā)表于 07-22 21:47
位域使用問題
在支持位操作的單片機(jī)中,如C51,使用位域定義變量或者寄存器,操作方便并且節(jié)約空間。 問題1:但是很多單片機(jī)不支持位操作,仍然使用位
發(fā)表于 09-16 22:25
MISRA C編程規(guī)范標(biāo)準(zhǔn)有什么規(guī)則要求?
如何衡量代碼是否滿足某些標(biāo)準(zhǔn)?MISRA C編程規(guī)范標(biāo)準(zhǔn)有什么規(guī)則要求?
發(fā)表于 04-19 07:20
你所不知道的關(guān)于iPhone7的幾個真相,看完讓所有人震驚!
Phone7發(fā)布這么久了,你用的還好嗎?希望你的iPhone不要出現(xiàn)掉漆等不好的現(xiàn)象。你們在使用的過程中有沒有發(fā)現(xiàn)iPhone7什么不為人知的秘密呢?如果沒發(fā)現(xiàn)的話,下面我就來告訴大家關(guān)于iPhone7的一些
發(fā)表于 02-23 09:40
?3531次閱讀
什么是分層架構(gòu)的依據(jù)與原則?本文告訴你答案!
分層架構(gòu)是運(yùn)用最為廣泛的架構(gòu)模式,幾乎每個軟件系統(tǒng)都需要通過層(Layer)來隔離不同的關(guān)注點(diǎn)(Concern Point),以此應(yīng)對不同需求的變化,使得這種變化可以獨(dú)立進(jìn)行;此外,分層架構(gòu)模式還是隔離業(yè)務(wù)復(fù)雜度與技術(shù)復(fù)雜度的利器,《領(lǐng)域驅(qū)動設(shè)計模式、原理與實(shí)踐》寫道:
發(fā)表于 07-27 14:16
?7757次閱讀
如何區(qū)分FPGA與CPLD?本文告訴你答案!
如何區(qū)分CPLD或FPGA和哪一個更適合自己?這是一個老生常談的問題,尤其是學(xué)生和初學(xué)者。如果您也在這個問題上很迷茫,那么就請聽小編為您區(qū)分FPGA與CPLD。
發(fā)表于 09-04 14:16
?2480次閱讀
智能音箱究竟有哪些用處?本文告訴你答案!
在許多人心中一直以來都有個困惑,智能音箱到底有什么作用?無可否認(rèn),智能音箱能夠讓我們解放雙手,只通過語音就能夠進(jìn)行操作。智能音箱也能夠打通許多智能家居通道,消費(fèi)者能夠舒服的躺在沙發(fā)上控制家中燈光、電視、空調(diào)等電器是多么愜意的一件事。但這里有一個問題,能用智能音箱辦到的事情,使用智能手機(jī)也一樣可以做到,兩者似乎在這一點(diǎn)上有很多功能重合。
發(fā)表于 09-20 16:46
?2626次閱讀
怎么分辨機(jī)器人種類 本文告訴你答案
自20世紀(jì)中期出現(xiàn)的第一臺現(xiàn)代機(jī)器人后,隨著相關(guān)技術(shù)的快速演進(jìn),時至今日,機(jī)器人已廣泛地被應(yīng)用在許多不同的領(lǐng)域,來協(xié)助或取代人類完成各式各樣的工作。依照不同的需求,將機(jī)器人做出不同的分類,以達(dá)到有效區(qū)分或辨識他們的目的。
發(fā)表于 01-14 15:41
?5280次閱讀
2018的量子計算是怎么跟AI一起兩開花的 本文告訴你答案
回首剛剛過去的2018,如果讓我回答一個“科技產(chǎn)業(yè)怎么看”的問題。那答案應(yīng)該是這樣的:上看AI,下看IoT,近看5G,遠(yuǎn)看量子計算,千萬不要看區(qū)塊鏈,因為太亂,看了容易上頭。
發(fā)表于 01-15 10:16
?954次閱讀
怎么放置洗衣機(jī)最好 本文告訴你答案
洗衣機(jī)可以說是家里很重要的一種電器了,沒有洗衣機(jī)的時候,人們只能辛辛苦苦的用手來洗衣服,不僅傷手而且效率還很低,但是自從有了洗衣機(jī),我們的生活的確是方便了很多。不過,通常人們喜歡把洗衣機(jī)放在陽臺上,但是小編不建議大家這樣做,最好還是放在衛(wèi)生間。
發(fā)表于 02-15 11:40
?975次閱讀
智慧城市該如何建設(shè) 本文告訴你答案
智慧城市建設(shè)興起于歐美地區(qū),世界各國都將發(fā)展智慧城市定為未來幾年的目標(biāo)。我國雖起步較晚,但在政府的支持和企業(yè)的參與下,智慧城市建設(shè)也取得階段性進(jìn)展,在我國目前已有超過500個城市開展了相關(guān)建設(shè)。隨著人工智能、云計算、大數(shù)據(jù)等技術(shù)成熟,我國智慧城市發(fā)展將逐步向數(shù)據(jù)共享、萬物互聯(lián)、生態(tài)共贏邁進(jìn)。
發(fā)表于 05-29 08:53
?1418次閱讀
一文告訴你單相電機(jī)運(yùn)轉(zhuǎn)無力該如何檢測
本文小編告訴大家單相電機(jī)運(yùn)轉(zhuǎn)無力的3個檢測方法。
一文告訴你為什么電機(jī)過載保護(hù)元件常用熱繼電器?
小編告訴大家電機(jī)過載保護(hù)元件常用的是熱繼電器,因為它能滿足一些要求。
服務(wù)器ups運(yùn)行時間,圖文告訴你關(guān)于UPS電源的一些基礎(chǔ)知識
原標(biāo)題:圖文告訴你關(guān)于UPS電源的一些基礎(chǔ)知識UPS - Uninterrupted Power System利用電池化學(xué)能作為后備能量,在市電斷電等電網(wǎng)故障時,不間斷地為用戶設(shè)備提供(交流)電能
發(fā)表于 11-08 19:21
?8次下載
評論