0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

為什么MISRA要求你不要使用位域-本文告訴你真相

嵌入式USB開(kāi)發(fā) ? 來(lái)源:嵌入式Lee ? 作者:嵌入式Lee ? 2023-06-21 17:36 ? 次閱讀

本文轉(zhuǎn)自公眾號(hào),歡迎關(guān)注

為什么MISRA要求你不要使用位域-本文告訴你真相 (qq.com)

一.前言

做過(guò)嵌入式開(kāi)發(fā)的一般會(huì)看到一條編程規(guī)范:”不要使用位域”,一般都是知其然不其所以然,了解的多一點(diǎn)的可能知道位域是實(shí)現(xiàn)相關(guān)不具備可移植性,那么繼續(xù)追問(wèn)哪些行為是實(shí)現(xiàn)相關(guān)哪些行為導(dǎo)致移植性問(wèn)題? 或者還有人知道,存儲(chǔ)布局,對(duì)齊等行為是實(shí)現(xiàn)相關(guān)會(huì)導(dǎo)致不可移植性。如果再追問(wèn)位域產(chǎn)生的匯編代碼是什么樣的,怎么進(jìn)行讀-修改-寫(xiě)操作的?知道這些內(nèi)容的就更加少之又少了。 讀寫(xiě)肯定不能讀指定位數(shù),只能字節(jié),或者16位,32位這種,那么編譯器到底讀寫(xiě)用什么寬度? 這時(shí)基本大部分人都不知道了。

知其然知其所以然,尤其是嵌入式開(kāi)發(fā)和硬件結(jié)合比較緊密,所以一定要了解細(xì)節(jié),我們這一篇從一個(gè)問(wèn)題引出然后去分析查找原因,只有遇到問(wèn)題然后去分析解決它才會(huì)有更深刻的映像。

二.問(wèn)題分析過(guò)程

問(wèn)題是驅(qū)動(dòng)程序中一個(gè)寄存器的某個(gè)位域修改,導(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

34b4c4c2-0f04-11ee-9c1d-dac502259ad0.png

nfc_base[id]->nfc_ena._b.nfc_data_len= len

匯編代碼被優(yōu)化為了寫(xiě)高16位

34d22efe-0f04-11ee-9c1d-dac502259ad0.png

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

34f0fab4-0f04-11ee-9c1d-dac502259ad0.png

這是因?yàn)榧拇嫫饔布现恢С?2位的寫(xiě)操作,所以寫(xiě)高16位導(dǎo)致低16位清零了,這是硬件決定的。

二.驗(yàn)證

一般想到的就是優(yōu)化相關(guān),加volatile等,我們分別驗(yàn)證下。

3.1不使能編譯器優(yōu)化

編譯器優(yōu)化選項(xiàng)改為”-O0”

代碼不變

依然會(huì)按照16位訪問(wèn),導(dǎo)致低16位被清掉。

所以可以看到這個(gè)和編譯器行為有關(guān),編譯器顯然不是根據(jù)優(yōu)化等級(jí)決定位域的操作寬度,這里而是根據(jù)位域的寬度剛好是16位對(duì)齊,所以優(yōu)化為了16位操作指令。

3504cddc-0f04-11ee-9c1d-dac502259ad0.png351f3d70-0f04-11ee-9c1d-dac502259ad0.png

3.2使用volatile避免編譯器優(yōu)化

#ifndef__IOM

#define__IOM volatile

#endif

所有uint32_t替換為_(kāi)_IOM uint32_t

還是一樣的

353ad710-0f04-11ee-9c1d-dac502259ad0.png

顯然匯編代碼的訪問(wèn)寬度也不受volatile影響。

3.3為什么指定了uint32_t和volatile還會(huì)優(yōu)化。

問(wèn)題來(lái)了為什么告訴了編譯器是uint32_t和volatile,為什么其還要一意孤行,要優(yōu)化為16位訪問(wèn)指令呢,答案就是因?yàn)槭菢?biāo)準(zhǔn)沒(méi)有規(guī)定,這是編譯器實(shí)現(xiàn)行為決定的,所以編譯器設(shè)計(jì)者決定的(當(dāng)然也會(huì)有一些現(xiàn)實(shí)考慮的),可能不同編譯器行為不同,這里以GCC為例。

GCC編譯器文檔中可以找到答案

GCC的文檔可以看到如下內(nèi)容,也給出了最好是不使用位域的原因

354f86f6-0f04-11ee-9c1d-dac502259ad0.png

35645612-0f04-11ee-9c1d-dac502259ad0.png

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

3576ae5c-0f04-11ee-9c1d-dac502259ad0.png

那么有沒(méi)有辦法指定編譯按照一定大小訪問(wèn)呢,GCC有編譯選項(xiàng)可以控制見(jiàn)下一節(jié)。

3.4使用編譯器選項(xiàng)-fstrict-volatile-bitfields

358c8eca-0f04-11ee-9c1d-dac502259ad0.png

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

359dc4f6-0f04-11ee-9c1d-dac502259ad0.png

四.一些廠家做法

如下可見(jiàn)

4.1CMSIS

core_cmxx.h中定義

CMSIS中進(jìn)行了定義,寄存器個(gè)別使用位域

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),一般不建議使用位域,因?yàn)樯婕暗轿挥虻脑L問(wèn),存儲(chǔ)等行為都是實(shí)現(xiàn)定義的,不具備可移植性。

嵌入式領(lǐng)域寄存器的定義也最好不要使用位域,到寄存器級(jí)別以寄存器操作為單位即可,每個(gè)寄存器都要使用__IM,__OM,__IOM描述。

如果一定要使用位域可以使用-fstrict-volatile-bitfields選項(xiàng),使用GCC測(cè)試可以保證按照固定指定大小訪問(wèn),但是不保證其他編譯器也支持該選項(xiàng),最好能不使用就不使用位域。


審核編輯黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5046

    文章

    18821

    瀏覽量

    298623
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5253

    瀏覽量

    119212
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1602

    瀏覽量

    48896
  • MISRA
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    6945
  • 嵌入式編程
    +關(guān)注

    關(guān)注

    0

    文章

    26

    瀏覽量

    10279
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    IC設(shè)計(jì):ram的應(yīng)用-異步時(shí)鐘寬轉(zhuǎn)換

    在進(jìn)行模塊設(shè)計(jì)時(shí),我們經(jīng)常需要進(jìn)行數(shù)據(jù)寬的轉(zhuǎn)換,常見(jiàn)的兩種轉(zhuǎn)換場(chǎng)景有同步時(shí)鐘寬轉(zhuǎn)換和異步時(shí)鐘寬轉(zhuǎn)換。
    的頭像 發(fā)表于 11-23 16:41 ?649次閱讀
    IC設(shè)計(jì):ram的應(yīng)用-異步時(shí)鐘<b class='flag-5'>域</b><b class='flag-5'>位</b>寬轉(zhuǎn)換

    使用問(wèn)題

    在支持操作的單片機(jī)中,如C51,使用定義變量或者寄存器,操作方便并且節(jié)約空間。 問(wèn)題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的幾個(gè)真相,看完讓所有人震驚!

    Phone7發(fā)布這么久了,用的還好嗎?希望你的iPhone不要出現(xiàn)掉漆等不好的現(xiàn)象。你們?cè)谑褂玫倪^(guò)程中有沒(méi)有發(fā)現(xiàn)iPhone7什么不為人知的秘密呢?如果沒(méi)發(fā)現(xiàn)的話,下面我就來(lái)告訴大家關(guān)于iPhone7的一些
    發(fā)表于 02-23 09:40 ?3415次閱讀

    什么是分層架構(gòu)的依據(jù)與原則?本文告訴答案!

    分層架構(gòu)是運(yùn)用最為廣泛的架構(gòu)模式,幾乎每個(gè)軟件系統(tǒng)都需要通過(guò)層(Layer)來(lái)隔離不同的關(guān)注點(diǎn)(Concern Point),以此應(yīng)對(duì)不同需求的變化,使得這種變化可以獨(dú)立進(jìn)行;此外,分層架構(gòu)模式還是隔離業(yè)務(wù)復(fù)雜度與技術(shù)復(fù)雜度的利器,《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式、原理與實(shí)踐》寫(xiě)道:
    發(fā)表于 07-27 14:16 ?7340次閱讀
    什么是分層架構(gòu)的依據(jù)與原則?<b class='flag-5'>本文告訴</b><b class='flag-5'>你</b>答案!

    如何區(qū)分FPGA與CPLD?本文告訴答案!

    如何區(qū)分CPLD或FPGA和哪一個(gè)更適合自己?這是一個(gè)老生常談的問(wèn)題,尤其是學(xué)生和初學(xué)者。如果您也在這個(gè)問(wèn)題上很迷茫,那么就請(qǐng)聽(tīng)小編為您區(qū)分FPGA與CPLD。
    發(fā)表于 09-04 14:16 ?2099次閱讀
    如何區(qū)分FPGA與CPLD?<b class='flag-5'>本文告訴</b><b class='flag-5'>你</b>答案!

    智能音箱究竟有哪些用處?本文告訴答案!

    在許多人心中一直以來(lái)都有個(gè)困惑,智能音箱到底有什么作用?無(wú)可否認(rèn),智能音箱能夠讓我們解放雙手,只通過(guò)語(yǔ)音就能夠進(jìn)行操作。智能音箱也能夠打通許多智能家居通道,消費(fèi)者能夠舒服的躺在沙發(fā)上控制家中燈光、電視、空調(diào)等電器是多么愜意的一件事。但這里有一個(gè)問(wèn)題,能用智能音箱辦到的事情,使用智能手機(jī)也一樣可以做到,兩者似乎在這一點(diǎn)上有很多功能重合。
    發(fā)表于 09-20 16:46 ?2291次閱讀

    怎么分辨機(jī)器人種類 本文告訴答案

    自20世紀(jì)中期出現(xiàn)的第一臺(tái)現(xiàn)代機(jī)器人后,隨著相關(guān)技術(shù)的快速演進(jìn),時(shí)至今日,機(jī)器人已廣泛地被應(yīng)用在許多不同的領(lǐng)域,來(lái)協(xié)助或取代人類完成各式各樣的工作。依照不同的需求,將機(jī)器人做出不同的分類,以達(dá)到有效區(qū)分或辨識(shí)他們的目的。
    發(fā)表于 01-14 15:41 ?4908次閱讀

    2018的量子計(jì)算是怎么跟AI一起兩開(kāi)花的 本文告訴答案

    回首剛剛過(guò)去的2018,如果讓我回答一個(gè)“科技產(chǎn)業(yè)怎么看”的問(wèn)題。那答案應(yīng)該是這樣的:上看AI,下看IoT,近看5G,遠(yuǎn)看量子計(jì)算,千萬(wàn)不要看區(qū)塊鏈,因?yàn)樘珌y,看了容易上頭。
    發(fā)表于 01-15 10:16 ?813次閱讀

    怎么放置洗衣機(jī)最好 本文告訴答案

    洗衣機(jī)可以說(shuō)是家里很重要的一種電器了,沒(méi)有洗衣機(jī)的時(shí)候,人們只能辛辛苦苦的用手來(lái)洗衣服,不僅傷手而且效率還很低,但是自從有了洗衣機(jī),我們的生活的確是方便了很多。不過(guò),通常人們喜歡把洗衣機(jī)放在陽(yáng)臺(tái)上,但是小編不建議大家這樣做,最好還是放在衛(wèi)生間。
    發(fā)表于 02-15 11:40 ?728次閱讀

    智慧城市該如何建設(shè) 本文告訴答案

    智慧城市建設(shè)興起于歐美地區(qū),世界各國(guó)都將發(fā)展智慧城市定為未來(lái)幾年的目標(biāo)。我國(guó)雖起步較晚,但在政府的支持和企業(yè)的參與下,智慧城市建設(shè)也取得階段性進(jìn)展,在我國(guó)目前已有超過(guò)500個(gè)城市開(kāi)展了相關(guān)建設(shè)。隨著人工智能、云計(jì)算、大數(shù)據(jù)等技術(shù)成熟,我國(guó)智慧城市發(fā)展將逐步向數(shù)據(jù)共享、萬(wàn)物互聯(lián)、生態(tài)共贏邁進(jìn)。
    發(fā)表于 05-29 08:53 ?1238次閱讀
    智慧城市該如何建設(shè) <b class='flag-5'>本文告訴</b><b class='flag-5'>你</b>答案

    文告訴單相電機(jī)運(yùn)轉(zhuǎn)無(wú)力該如何檢測(cè)

    本文小編告訴大家單相電機(jī)運(yùn)轉(zhuǎn)無(wú)力的3個(gè)檢測(cè)方法。
    的頭像 發(fā)表于 12-14 21:28 ?1822次閱讀

    文告訴為什么電機(jī)過(guò)載保護(hù)元件常用熱繼電器?

    小編告訴大家電機(jī)過(guò)載保護(hù)元件常用的是熱繼電器,因?yàn)樗軡M足一些要求。
    的頭像 發(fā)表于 12-14 22:09 ?2453次閱讀

    文告訴什么是電機(jī)短時(shí)運(yùn)行?

    本文小編告訴大家什么是電機(jī)短時(shí)運(yùn)行。
    的頭像 發(fā)表于 12-14 22:12 ?2577次閱讀

    服務(wù)器ups運(yùn)行時(shí)間,圖文告訴關(guān)于UPS電源的一些基礎(chǔ)知識(shí)

    原標(biāo)題:圖文告訴關(guān)于UPS電源的一些基礎(chǔ)知識(shí)UPS - Uninterrupted Power System利用電池化學(xué)能作為后備能量,在市電斷電等電網(wǎng)故障時(shí),不間斷地為用戶設(shè)備提供(交流)電能
    發(fā)表于 11-08 19:21 ?8次下載
    服務(wù)器ups運(yùn)行時(shí)間,圖<b class='flag-5'>文告訴</b><b class='flag-5'>你</b>關(guān)于UPS電源的一些基礎(chǔ)知識(shí)