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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > DSP編程技巧之34---答疑解惑哪家強之(9)

          DSP編程技巧之34---答疑解惑哪家強之(9)

          —— DSP編程技巧之33---答疑解惑哪家強之(9)
          作者:paradoxfx 時間:2015-01-08 來源:電子產(chǎn)品世界 收藏

            答疑解惑哪家強?當(dāng)屬我們EEPW最強。。。接下來繼續(xù)我們的答疑解惑系列。

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

            58. 為什么一個看起來很簡單的程序,鏈接的時候卻要花費很長的時間?

            導(dǎo)致這種現(xiàn)象的最主要的原因是類型合并(type merging)。那什么是類型合并呢?舉個簡單的例子,在頭文件types.h中定義了結(jié)構(gòu)sss,且所有的.c中中都引用了這個types.h。因此在編譯之后,描述sss的調(diào)試類型信息被包含到每個目標文件之中(除非使用了--symdebug:none來禁用調(diào)試信息),因此在鏈接的時候,鏈接器會發(fā)現(xiàn)有很多個sss類型的副本;默認情況下,鏈接器使用類型合并把這么多sss類型合并為一個,從而使得最終輸出的.out文件中只有一個sss類型,而不是很多個重復(fù)的副本,達到減小代碼尺寸的目的,并且使得CCS在加載.out文件時也會花費更少的時間。然后,類型合并這個過程中需要大量的計算,因此導(dǎo)致了鏈接看起來需要花費很長的時間。

            解決的方法有兩個:

            1. 禁用類型合并:使用鏈接器的-b選項(含義請參考http://www.ex-cimer.com/article/249328.htm)。這樣做的結(jié)果是鏈接的時間變短,但是.out文件變大,需要更長的時間來加載;如果在這個例子中sss的副本非常多,有可能需要很差的時間來加載.out文件。

            2. 使用--symdebug:none選項來完全禁止把調(diào)試信息寫入.out文件。這樣做既可以減小鏈接時間,又可以減小.out的尺寸和縮短加載時間,但后果是代碼的調(diào)試功能被大大削弱了。

            59. 如何使用一個.cmd文件在含有不同的內(nèi)部存儲空間的芯片上來實現(xiàn)段的優(yōu)先級?

            假設(shè)有下面的狀況:

            器件1有64kb快速的內(nèi)部存儲,而器件2有128kb?,F(xiàn)在我們有4個關(guān)鍵的代碼段:

             .text:_a : 20kb

             .text:_b : 30kb

             .text:_c : 20kb

             .text:_d : 10kb

            其中段a的運算重要性最高,段b的次之,以此類推。

            給片內(nèi)的快速存儲器命名為IRAM,而片外的慢速存儲器命名為SDRAM。假設(shè)在器件1上,我們必須把.text:_a和.text:_b保存在IRAM中以保證運行速度,而.text:_c和.text:_d則既可以保存在IRAM,也可以保存在SDRAM中。在器件2中,因為片上存儲顯著增大,可以把abcd四個段都保存在SDRAM中。此時我們可以使用下面的方式,使用同一個.cmd文件來完成段的分配:

            這一段語句的作用有兩個:

            (1) 在分配存儲空間時,按照順序來確保配段的優(yōu)先級。在.cmd文件中,如果需要保證段的優(yōu)先級,則必須使用GROUP這個指令;如果不使用則段之間不會有優(yōu)先級的關(guān)系,此時鏈接器會有效把長度最大的那個段優(yōu)先分配空間,以最大程度地減少存儲空間中的空隙。

            (2) 自動在不相鄰的存儲空間IRAM和SDRAM中劃分輸出的段。兩個大于號“>>”也是鏈接器的內(nèi)部指令,它用來表明GROUP中的段可以被劃分到不同的存儲空間里。例如,當(dāng)鏈接器在器件1上,發(fā)現(xiàn)在分配完.text:_a和.text:_b到IRAM中之后,發(fā)現(xiàn).text:_c有20kb,IRAM的空間已經(jīng)不足以存放它時,它會跳過把text:_c分配到IRAM上,而是把text:_c分配到SDRAM中;接下來鏈接器會繼續(xù)嘗試把text:_d給分配到IRAM中(如果text:_d的長度足夠小的話)。而在器件2上,編譯器會發(fā)現(xiàn)空間足夠存放abcd四個段的時候,就把它們四個一起保存到IRAM中了。

            如果我們使用下面的兩種方式,結(jié)果會是什么樣的呢?

            使用這個方法仍然可以做到段的分割,即上面的第二條,然而它們之間空間分配的優(yōu)先級沒有辦法保證,很有可能使得程序的性能受到影響。

            使用這個方法仍然可以做到段的優(yōu)先級,即上面的第一條,然而在器件1上這些段將無法全部保存到IRAM中,最終導(dǎo)致鏈接器的錯誤。。

            60. 為什么需要開啟鏈接器–w選項?

            -w的含義是:在未定義的輸出段被創(chuàng)建時產(chǎn)生警告信息。因此,如果我們在程序中創(chuàng)建了段,例如:

            但是在cmd文件中沒有明確段的類型(例如.text、.bss等),則鏈接器將有可能任意地給我們自定義的段分配一個地址控制,這將導(dǎo)致嚴重的運行時錯誤。例如,鏈接器有可能任意地把我們自定義的段給分配為FLASH這個段類型,但是實際上它們并不在Flash中運行,結(jié)果導(dǎo)致代碼完全不執(zhí)行。

            使用-w選項將使得鏈接器必須提示我們有關(guān)段未定義的信息,從而避免上述問題的發(fā)生。

            61. 鏈接器地址映射文件中的trampolines代表什么含義?

            在鏈接之后,打開生成的.map文件,可以查看地址映射信息,如下圖所示。

            其中的TRAMPOLINES在英語里是“蹦床”的有意思,在這里的含義則是代表非直接跳轉(zhuǎn)的向量。它的含義與蹦床運動是一樣的,代碼執(zhí)行到trampoline之后會立刻跳轉(zhuǎn)出,或者回彈。當(dāng)跳轉(zhuǎn)指令無法到達目的地時,鏈接器會自動產(chǎn)生trampoline, 然后我們就可以看到上圖所示的那些信息了,它們的含義是:

             callee:函數(shù)被調(diào)用。

             addr:callee的地址。

             tramp:鏈接器自動為trampoline所產(chǎn)生的名字。

             addr:trampoline在存儲器中的地址。

             call addr:從trampoline產(chǎn)生的調(diào)用所使用的地址列表。

             call info:包含最初調(diào)用的目標文件和輸入段。如果目標文件保存在某個庫中,則會把庫文件的名字也顯示出來。

          62. 在C編譯器中使用內(nèi)聯(lián)的匯編指令的情況下,為何代碼的實時運行出錯了?

            在C代碼中,我們可以使用asm()指令來插入?yún)R編代碼。如果插入的這段匯編代碼修改了C代碼所使用的運行環(huán)境中的寄存器,則會破壞C代碼的數(shù)據(jù),導(dǎo)致運行時出錯。所有在C代碼中使用內(nèi)聯(lián)的匯編代碼時務(wù)必小心,不要破壞了程序的完整性。



          關(guān)鍵詞: DSP 編程

          評論


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