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

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(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

          本章主要介紹嵌入式應(yīng)用程序的設(shè)計(jì)方法。本章中的一些實(shí)例程序是以ARM公司的Realview2.2為開發(fā)平臺(tái)。由于目前嵌入式應(yīng)用環(huán)境相差非常大,這里主要是通過這些實(shí)例程序來更直接地介紹嵌入式應(yīng)用系統(tǒng)的開發(fā)方法,具體的代碼因具體的嵌入式環(huán)境不同而有所差異。

          13.1 基于設(shè)計(jì)

          ARM系列處理器是RISC(Reducded Instruction Set Computing)處理器。很多基于ARM的高效代碼的程序設(shè)計(jì)策略都源于RISC處理器。和很多RISC處理器一樣,ARM系列處理器的內(nèi)存訪問也要求數(shù)據(jù)對(duì)齊,即存取“字(Word)”數(shù)據(jù)時(shí)要求四字節(jié)對(duì)齊,地址的bits[1:0]=0b00;存取“半字(Halfwords)”時(shí)要求兩字節(jié)對(duì)齊,地址的bit[0]=0b0;存取“字節(jié)(Byte)”數(shù)據(jù)時(shí)要求該數(shù)據(jù)按其自然尺寸邊界(Natural Size Boundary)定位。

          ARM編譯程序通常將全局變量對(duì)齊到自然尺寸邊界上,以便通過使用 LDR和STR指令有效地存取這些變量。

          這種內(nèi)存訪問方式與多數(shù)CISC(Complex Instruction Set Computing)體系結(jié)構(gòu)不同,在CISC體系結(jié)構(gòu)下,指令直接存取未對(duì)齊的數(shù)據(jù)。因而,當(dāng)需要將代碼從CISC體系結(jié)構(gòu)向 移植時(shí),內(nèi)存訪問的地址對(duì)齊問題必須予以注意。在RISC體系結(jié)構(gòu)下,存取未對(duì)齊數(shù)據(jù)無論在代碼尺寸或是程序執(zhí)行效率上,都將付出非常大的代價(jià)。

          注意

          在ARM11處理器上,新增加了支持非內(nèi)存對(duì)齊數(shù)據(jù)訪問的硬件,此結(jié)構(gòu)在本章中不作討論。

          下面將從4個(gè)方面詳細(xì)討論在ARM體系結(jié)構(gòu)下的程序設(shè)計(jì):

          · 未對(duì)齊指針;

          · 結(jié)構(gòu)體中的;

          · 用于半字存取的Load指令;

          · 移植代碼并檢測(cè)非對(duì)齊存取。

          13.1.1 未對(duì)齊的

          C和C++編程標(biāo)準(zhǔn)規(guī)定,指向某一數(shù)據(jù)類型的指針,必須和該類型的數(shù)據(jù)地址對(duì)齊方式一致,所以ARM編譯器期望程序中的C指針指向存儲(chǔ)器中字對(duì)齊地址,因?yàn)檫@可使編譯器生成更高效的代碼。

          比如,如果定義一個(gè)指向int數(shù)據(jù)類型的指針,用該指針讀取一個(gè)字,ARM 編譯器將使用LDR指令來完成此操作。如果讀取的地址為4的倍數(shù)(即在一個(gè)字的邊界)即能正確讀取。但是,如果該地址不是4的倍數(shù),那么,一條LDR指令返回一個(gè)循環(huán)移位結(jié)果,而不是執(zhí)行真正的未對(duì)齊字載入。循環(huán)移位結(jié)果取決于該地址相對(duì)于字的邊界的偏移量和系統(tǒng)所使用的端序(Endianness)。例如,如果代碼要求從指針指向的地址0x8006載入數(shù)據(jù),即要載入0x8006、0x8007、0x8008和0x8009 4個(gè)字節(jié)的內(nèi)容。但是,在上,這個(gè)存取操作載入了0x8004、0x8005、0x8006和0x8007字節(jié)的內(nèi)容。這就是在未對(duì)齊的地址上使用指針存取所得到的循環(huán)移位結(jié)果。

          因而,如果想將指針定義到一個(gè)指定地址(該地址為非自然邊界對(duì)齊),那么在定義該指針時(shí),必須使用__packed限定符來定義指針:

          例如:

          __packed int *pi; // 指針指向一個(gè)非字對(duì)其內(nèi)存地址

          使用了__packed限定符限定之后,ARM編譯器將產(chǎn)生字節(jié)存取命令(LDRB或STRB指令)來存取內(nèi)存,這樣就不必考慮指針對(duì)齊問題。所生成的代碼是字節(jié)存取的一個(gè)序列,或者取決于編譯選項(xiàng)、跟變量對(duì)齊相關(guān)的移位和屏蔽。但這會(huì)導(dǎo)致系統(tǒng)性能和代碼密度的損失。

          值得注意的是,不能使用__packed限定的指針來存取存儲(chǔ)器映射的外圍寄存器,因?yàn)锳RM編譯程序可使用多個(gè)存儲(chǔ)器存取來獲取數(shù)據(jù)。因而,可以對(duì)實(shí)際存取地址附近的位置進(jìn)行存取,而這些附近的位置可能對(duì)應(yīng)于其他外部寄存器。當(dāng)使用了位字段(Bitfield)時(shí),ARM程序?qū)⒃L問整個(gè)結(jié)構(gòu)體,而非指定字段。

          13.1.2 結(jié)構(gòu)體中

          與全局變量位于其自然尺寸邊界相同,結(jié)構(gòu)體(Structure)中的域字段(Filed)也如此。也就是說編譯程序經(jīng)常要在字段間插入填充字節(jié)(Padding)來確保域字段對(duì)齊。當(dāng)編譯程序插入填充字節(jié)時(shí),編譯器將產(chǎn)生以下警告信息。

          #1301-D: padding inserted in struct mystruct

          可以使用-remark編譯選項(xiàng)使編譯器產(chǎn)生備份信息,或使用-diag_warning選項(xiàng)選擇編譯器產(chǎn)生的備份信息。

          如果不希望編譯器產(chǎn)生填充字節(jié),可以使用__packed限定符來創(chuàng)建字段之間沒有填充字節(jié)的結(jié)構(gòu),且這些結(jié)構(gòu)需要非對(duì)齊存取。

          如果ARM編譯器能夠確定所訪問結(jié)構(gòu)體的對(duì)齊方式,那么它就可以自動(dòng)識(shí)別所存取結(jié)構(gòu)體中的字段的對(duì)齊方式。在這些情況下,編譯程序盡可能地采用更有效的對(duì)齊字或半字存取方式。否則,編譯器將使用多個(gè)對(duì)齊存儲(chǔ)器存取(LDR、STR、LDM和STM)與固定移位和屏蔽相結(jié)合來存取存儲(chǔ)器中的字節(jié)。

          對(duì)非對(duì)齊元素的存取是通過內(nèi)聯(lián)還是通過調(diào)用一個(gè)函數(shù)來完成,由編譯程序-Ospace(默認(rèn),調(diào)用一個(gè)函數(shù))和-Otime(執(zhí)行非對(duì)齊存取內(nèi)聯(lián))選項(xiàng)來控制。

          例如:

          創(chuàng)建一個(gè)名為foo.c源文件。

          __packed struct mystruct {

          int aligned_i;

          short aligned_s;

          int unaligned_i;

          };

          struct mystruct S1;

          int foo (int a, short b)

          {

          S1.aligned_i=a;

          S1.aligned_s=b;

          return S1.unaligned_i;

          }

          使用armcc -c -Otime foo.c編譯。所生成的代碼為:

          MOV r2,r0

          LDR r0,|L1.84|

          MOV r12,r2,LSR #8

          STRB r2,[r0,#0]

          STRB r12,[r0,#1]

          MOV r12,r2,LSR #16

          STRB r12,[r0,#2]

          MOV r12,r2,LSR #24

          STRB r12,[r0,#3]

          MOV r12,r1,LSR #8

          STRB r1,[r0,#4]

          STRB r12,[r0,#5]

          ADD r0,r0,#6

          BIC r3,r0,#3

          AND r0,r0,#3

          LDMIA r3,{r3,r12}

          MOV r0,r0,LSL #3

          MOV r3,r3,LSR r0

          RSB r0,r0,#0x20

          ORR r0,r3,r12,LSL r0

          BX lr

          其中,“|L1.84|”為結(jié)構(gòu)體mystruct在內(nèi)存中的地址。

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



          上一頁(yè) 1 2 下一頁(yè)

          評(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); })();