<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 嵌入式軟件開發(fā)之: 基于ARM處理器的嵌入式系統(tǒng)設(shè)計(jì)

          嵌入式軟件開發(fā)之: 基于ARM處理器的嵌入式系統(tǒng)設(shè)計(jì)

          作者: 時(shí)間:2013-09-30 來源:網(wǎng)絡(luò) 收藏

          本文引用地址:http://www.ex-cimer.com/article/257030.htm

          從上例可以看出,所有對(duì)結(jié)構(gòu)體域成員的訪問都是通過字節(jié)訪問實(shí)現(xiàn)的,所以這種不對(duì)齊內(nèi)存訪問無論從代碼占用的存儲(chǔ)器空間,還是代碼的執(zhí)行時(shí)間上都要付出一定的代價(jià)。

          然而,開發(fā)者可以給編譯器提供更多的信息,使其知道結(jié)構(gòu)體內(nèi)哪個(gè)字段是對(duì)齊的,哪個(gè)字段不是。為此,必須將聲明為__packed,并從struct本身除去__packed屬性。通過這種方法可以保證對(duì)struct中自然對(duì)齊成員的快速訪問。而且,哪個(gè)字段是未對(duì)齊的也更清楚,但這樣就增加了訪問struct結(jié)構(gòu)的難度,當(dāng)用戶從結(jié)構(gòu)中增加或刪除字段時(shí)需要特別小心。

          修改上例中結(jié)構(gòu)體的定義,來減少訪問結(jié)構(gòu)體的開銷。具體代碼如下所示。

          struct mystruct {

          int aligned_i;

          short aligned_s;

          __packed int unaligned_i;

          };

          struct mystruct S1;

          對(duì)修改后的程序進(jìn)行編譯,產(chǎn)生的匯編代碼如下所示。

          MOV r2,r0

          LDR r0,|L1.32|

          STR r2,[r0,#0]

          STRH r1,[r0,#4]

          LDMIB r0,{r3,r12}

          MOV r0,r3,LSR #16

          ORR r0,r0,r12,LSL #16

          BX lr

          從編譯后的匯編代碼不難看出,對(duì)結(jié)構(gòu)體內(nèi)符號(hào)自然邊界對(duì)齊的域,編譯器直接使用相應(yīng)的Load/Store指令進(jìn)行訪問,而只有那些非自然邊界對(duì)齊的域,編譯器才進(jìn)行附加處理。這樣,從時(shí)間和空間兩方面減小了程序的開銷。

          同一原理也適應(yīng)于聯(lián)合體結(jié)構(gòu)(unions)。使用在存儲(chǔ)器中未對(duì)齊的聯(lián)合組件的__packed屬性。

          13.1.3 用于半字存取的非對(duì)齊 LDR指令

          一些特殊情況下,ARM編譯程序可以生成非對(duì)齊LDR指令。特別是編譯程序從存儲(chǔ)器中載入半字時(shí)將使用該方法。這是因?yàn)?,通過使用相應(yīng)地址,所需的半字可以載入到寄存器的高半段(bits[31:16]),然后通過移位,將有效數(shù)據(jù)移到寄存器的低半段(bits[15:0])。這樣做的目的是通過減少內(nèi)存訪問次數(shù)來減少程序的執(zhí)行時(shí)間。通過上面的方法,程序只需要一次存儲(chǔ)器的訪問,而使用LDRB指令做同樣的操作需要兩次存儲(chǔ)器的存取,而且還要為將這兩個(gè)字節(jié)合并在一起添加特殊的代碼。在ARM體系結(jié)構(gòu)v3和其早期版本中,通常使用該方法進(jìn)行所有的半字載入。但在ARMv4及其以后版本中,出現(xiàn)了專門的半字載入指令,這種方法逐漸被取代。但是,非對(duì)齊LDR指令仍可能會(huì)出現(xiàn),比如在一個(gè)充填結(jié)構(gòu)中存取一個(gè)非對(duì)齊short域類型。

          注意

          在RVCT中已經(jīng)不再支持ARMv3架構(gòu)。

          13.1.4 移植代碼并檢測(cè)非對(duì)齊內(nèi)存訪問

          在非RISC體系結(jié)構(gòu)的處理器上執(zhí)行的代碼中,可能會(huì)存在使用指針訪問非自然邊界對(duì)齊的數(shù)據(jù)類型。這種操作,在ARM體系結(jié)構(gòu)中是不允許的。這就給代碼的移植帶來很大困難。用戶必須識(shí)別并更改此類內(nèi)存訪問代碼才能使其在RISC體系結(jié)構(gòu)的處理器上正確執(zhí)行。

          識(shí)別非對(duì)齊存取可能會(huì)很困難,因?yàn)槭褂梅菍?duì)齊地址進(jìn)行的載入或存儲(chǔ)操作會(huì)產(chǎn)生不正確的動(dòng)作。追蹤到底是哪部分的C源程序造成了這個(gè)問題是很困難的。

          具有完整存儲(chǔ)器管理單元(MMUs)的,例如ARM920TTM,支持內(nèi)存對(duì)齊檢測(cè)功能,用戶可以通過設(shè)置MMU使處理器檢測(cè)每一次的內(nèi)存訪問以確保其被正確地對(duì)齊。如果出現(xiàn)非對(duì)齊內(nèi)存訪問,MMU將產(chǎn)生數(shù)據(jù)中斷。這樣就給追蹤出錯(cuò)代碼帶來了很大的方便。

          對(duì)于一些簡(jiǎn)單的沒有MMU的內(nèi)核,如ARM7TDMI,最好的方法是在ASIC(Application Specific Integrated Circuit)/ASSP(Application Specific Standard Product)內(nèi)部實(shí)現(xiàn)對(duì)齊檢測(cè)??梢栽黾訉iT的ARM內(nèi)核擴(kuò)展硬件,由其監(jiān)控每次數(shù)據(jù)的訪問的內(nèi)存大小和存取地址總線的最低有效位。在非對(duì)齊存取的情況下,可以通過配置ASIC/ASSP產(chǎn)生中斷信號(hào)(ABORT)。ARM公司建議在需要運(yùn)行移植代碼設(shè)備中包含這樣的ASIC/ASSP邏輯。

          如果在設(shè)計(jì)系統(tǒng)時(shí),將系統(tǒng)設(shè)計(jì)成為當(dāng)出現(xiàn)非對(duì)齊的內(nèi)存訪問時(shí)產(chǎn)生異常,則必須安裝數(shù)據(jù)中斷異常處理程序(Data Abort Handler)。出現(xiàn)非對(duì)齊存取時(shí),程序進(jìn)入數(shù)據(jù)中斷處理程序,并由此識(shí)別位于返回地址(在LR中保存的地址)減8(r14-8)的出錯(cuò)數(shù)據(jù)存取指令。

          一旦出現(xiàn)數(shù)據(jù)中斷異常,必須通過改變C源程序來修復(fù)非對(duì)齊的數(shù)據(jù)訪問。使用下列指令可有條件地完成修復(fù):

          #ifdef __arm

          #define PACKED __packed

          #else

          #define PACKED

          #endif

          :

          PACKED int *pi;

          :

          由于代碼大小和性能上的開銷,最好盡可能少采用存取非對(duì)齊數(shù)據(jù)。

          ARM編譯器支持--pointer_alignment和--min_array_alignment與內(nèi)存對(duì)齊相關(guān)的編譯選項(xiàng),詳見ARM相關(guān)文檔。

          c++相關(guān)文章:c++教程



          上一頁 1 2 下一頁

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();