ARM嵌入式軟件開發(fā)課件_第1頁(yè)
ARM嵌入式軟件開發(fā)課件_第2頁(yè)
ARM嵌入式軟件開發(fā)課件_第3頁(yè)
ARM嵌入式軟件開發(fā)課件_第4頁(yè)
ARM嵌入式軟件開發(fā)課件_第5頁(yè)
已閱讀5頁(yè),還剩44頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

嵌入式軟件開發(fā)嵌入式開發(fā)過程“PC軟件”獨(dú)立的嵌入式應(yīng)用當(dāng)程序員開始開發(fā)一個(gè)基于ARM應(yīng)用的時(shí)候,你可以使用ARM的ADS編寫類似于“HELLOWORLD”的程序,使用ARMulator或者在評(píng)估板上來(lái)調(diào)試,但當(dāng)你把他移植到獨(dú)立的嵌入式應(yīng)用設(shè)備中時(shí),下面這些問題就成為我們首要考慮的:

硬件環(huán)境中所使用的C庫(kù)函數(shù)

目標(biāo)板上的存儲(chǔ)器資源

應(yīng)用程序的初始化議程PC軟件的構(gòu)造

定制標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板

復(fù)位和初始化

深層次的存儲(chǔ)器器映象考慮

編譯和調(diào)試IMAGEADS默認(rèn)的存儲(chǔ)器映射在默認(rèn)的情況下,我們鏈接、定位、運(yùn)行在0x8000heap被直接放置在數(shù)據(jù)區(qū)的上面堆棧的基地址是通過調(diào)試環(huán)境從C庫(kù)函數(shù)的StartupCode里讀取出來(lái)的。ARMulator=>fromconfigurationfile(peripherals.ami)default=0x08000000Multi-ICE=>fromdebuggerinternalvariable$top_of_memorydefault=0x80000RORWZI0x8000鏈接時(shí)確定由調(diào)試環(huán)境提供Heap(malloc,alloc)StackCLibraryUserCode應(yīng)用程序啟動(dòng)__maincopycodeanddatazerouninitializeddata__rt_entrysetupapplicationstackandheapinitializelibraryfunctionscalltop-levelconstructors(C++)Exitfromapplicationmain()causesthelinkertopullinlibraryinitializationcode程序入口點(diǎn)Agenda 一個(gè)PC軟件的構(gòu)造

定制標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板

復(fù)位和初始化

深層次的存儲(chǔ)器器映象考慮

編譯和調(diào)試IMAGE重定向C庫(kù)函數(shù)(2)要重定向C庫(kù)函數(shù),簡(jiǎn)單的辦法是使用你自己的可執(zhí)行的semihostingSWIs來(lái)代替原來(lái)的C庫(kù)函數(shù),從而來(lái)滿足你的系統(tǒng)要求

比如說(shuō),theprintf()系列函數(shù)(sprintf()除外)都會(huì)調(diào)用fputc().在默認(rèn)情況下fputc()的執(zhí)行使用了semihostingSWI.用下面的語(yǔ)句來(lái)代替:

externvoidsendchar(char*ch);

intfputc(intch,FILE*f)

{/*e.g.writeacharactertoanLCD*/

chartempch=ch;

sendchar(&tempch);

returnch;

}

可查看在ADSEmbeddedexample目錄下的retarget.c,可看到更多的重定向例子

你可以確定有不在連接時(shí)使用semihostingSWI的嗎?…...消除C庫(kù)函數(shù)中的semihosting為了確保在連接時(shí)沒有函數(shù)使用了semihostingSWIs,你可以在程序中加入下面的句子:#pragmaimport(__use_no_semihosting_swi)

如果在程序中仍然使用了semihosting,編譯時(shí)將會(huì)報(bào)錯(cuò):Error:Symbol__semihosting_swi_guardmultiplydefined修改:

如果使用(check-verboselinkeroutputforoccurrencesofIuse_semihosting_swi),那么連接器將會(huì)把那些使用了smeihosting的程序列出來(lái),

然后:提供你自己可運(yùn)行的功能函數(shù)。在ADS1.2編譯器和庫(kù)函數(shù)手冊(cè),表4-2給出了所有使用了semihosting的C庫(kù)函數(shù)。注意:連接器在用戶自己的應(yīng)用代碼中不會(huì)出現(xiàn)任何有關(guān)semihostingSWI使用的報(bào)告。Agenda

一個(gè)PC軟件的構(gòu)造

定制標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板

定制IMAGE的存儲(chǔ)器映射到目標(biāo)板

復(fù)位和初始化

深層次的存儲(chǔ)器器映象考慮

編譯和調(diào)試IMAGEExecuteViewRAM0x100000x180000x40000x0000ROMRO分散加載

(簡(jiǎn)單例子)只讀代碼和數(shù)據(jù)保存在ROM中C庫(kù)函數(shù)初始化代碼(在__main)將:從ROM拷貝RW數(shù)據(jù)到RAM在RAM中的ZI數(shù)據(jù)初始化RAM0x100000x180000x40000x0000ROMLoadViewRORWFillwithzerosZICopyRWExecuteViewRAM0x100000x180000x40000x0000ROMROLOAD_ROM0x00000x4000{}RAM0x100000x180000x40000x0000ROMLoadViewRORWScatter描述文件通配符(*)語(yǔ)法允許簡(jiǎn)單的對(duì)CODE和DATA進(jìn)行分組EXEC_ROM0x00000x4000{*(+RO)}RAM0x100000x8000{*(+RW,+ZI)}RWZIRORWZIROCODERO-DATARO-CODEAB鏈接器放置規(guī)則在每個(gè)可執(zhí)行區(qū),鏈接器通過一些基本的規(guī)則來(lái)放置CODE和DATA基本的排序方法是通過屬性來(lái)安排的:RO領(lǐng)先于RW,RW領(lǐng)先于ZI有相同的屬性時(shí),CODE在DATA之前放置。更多的排序方法決定于:輸入的組名按字母排序,

在ARMLINK命令行中指定的順序。eg:armlink…

AsectionAfromsectionAfromROOT區(qū)

LOAD_ROM0x00000x4000;startaddressandlength

{ EXEC_ROM0x00000x4000;root(load=execaddress){

__main.o(+RO);copyingcode*(Region$$Table);RO/RWaddressestocopy*(ZISection$$Table);ZIaddressestozero }

RAM0x100000x8000

{

*(+RO);AllotherROareas *(+RW,+ZI);programvariables

}

}Mustbeinarootregionoutsiderootregion一個(gè)root區(qū)是一個(gè)可執(zhí)行區(qū),它的加載地址等于執(zhí)行地址。Root區(qū)要點(diǎn)一個(gè)root區(qū)是一個(gè)可執(zhí)行區(qū),它的加載地址等于執(zhí)行地址.每個(gè)scatter描述文件必須最少包含一個(gè)root區(qū),并且最少要包含下列內(nèi)容:__main.o–含有拷貝code/data的代碼Region$$Table和ZISection$$Table–含有將要拷貝的code/data的地址,他是由鏈接器產(chǎn)生的,不是一個(gè)對(duì)象文件。(所以*必須用)

Error:L6202E:SectionRegion$$Tablecannotbeassignedtoanon-rootregion. Error:L6202E:SectionZISection$$Tablecannotbeassignedtoanon-rootregion.注意:如果

*(+RO)被定位在root區(qū),在此之前的將被自動(dòng)放置Main應(yīng)用程序的入口點(diǎn)必須放在root區(qū)。 Error:L6203E:Entrypoint(0x08000000)lieswithinnon-rootregionEXE_FLASH.Run-time存儲(chǔ)器管理SemihostingSupportANSICStack&HeapSetupStack&HeapSetupANSICCLibraryUserCodeDebugAgentTargetHardwareRetarget如何設(shè)置stack和heap來(lái)滿足我們的目標(biāo)存儲(chǔ)器?我們已經(jīng)通過執(zhí)行__user_initial_stackheap()把C標(biāo)準(zhǔn)庫(kù)的運(yùn)行存儲(chǔ)器模式修改到目標(biāo)平臺(tái)上。Run-time存儲(chǔ)器模式你必須決定在放置stack和heap時(shí)所使用的區(qū)域是單一的區(qū)(one-regionmodel)或是不同的兩個(gè)區(qū)(two-regionmodel)HeapStackStackOneregionmodelTworegionmodelHBSBSBHBHL單一存儲(chǔ)器模式是默認(rèn)方式為了實(shí)現(xiàn)多區(qū)域模式,你可以使用use_two_region_memory在所有的模式下,軟件堆棧檢查要許可。編譯開關(guān)是:-apcs/swst指定堆棧限制(為two-region模式)heapischeckedagainststackpointerHeapheapischeckedagainstheaplimit(SL)__user_initial_stackheap()可以用C或匯編來(lái)寫,他要返回:Heap基地址在R0,STACK的基地址在R1.Heap的限制地址在R2,STACK的限制地址在R3

EXPORT__user_initial_stackheap__user_initial_stackheap LDRr0,=0x80000;HB LDRr1,=0x88000;SB ;r2notused(HL) ;r3notused(SL) MOVpc,lrHeapStackHeap的限制地址在單一模式是不被使用的。Stack的限制地址只在軟件堆棧檢查許可的情況下才有效。HB=0x80000SB=0x88000警告!當(dāng)使用分散加載時(shí)你必須執(zhí)行__user_initial_stackheap()在C庫(kù)初始化代碼內(nèi)的__user_initial_stackheap()的默認(rèn)執(zhí)行是在映像文件的RW/ZI數(shù)據(jù)段后放置HEAP。使用Image$$RW$$Base/Image$$ZI$$Base

連接符號(hào)這些符號(hào)對(duì)scatterloading是無(wú)效的。在ADS1.1和早期版本的軟件中:符號(hào)被設(shè)置為0X0,heap被定位在這!Heap的并發(fā)使用,無(wú)論是直接(e.g.withmalloc())或間接(byuseofargc/argv)的都可能破壞向量表或其他代碼,典型的結(jié)果是不可預(yù)知的程序在運(yùn)行時(shí)出錯(cuò)了。在ADS1.2:符號(hào)沒有定義,應(yīng)用程序不會(huì)聯(lián)接:

Error:L6218E:UndefinedsymbolImage$$ZI$$Limit(referredfromsys_stackheap.o).TheVectorTable

AREAVectors,CODE,READONLY IMPORTReset_Handler

;importotherexceptionhandlers ;…ENTRY B Reset_Handler

B Undefined_Handler

B SWI_Handler

B Prefetch_Handler

B Data_Handler

NOP ;Reservedvector

B IRQ_Handler

;FIQ_Handlerwillfollowdirectly END在使用scatterloading+FIRST時(shí)直接定位在0X0(或0xFFFF0000)ENTRY

直接告訴鏈接器這是一個(gè)入口點(diǎn),防止某些段被刪除中斷向量表初始化步驟CLibraryUserCode__maincopycodeanddatazerouninitializeddata__rt_entryinitializelibraryfunctionscalltop-levelconstructors(C++)Exitfromapplicationmain()tellslinkertolinkinlibraryinitializationcodeImageEntryPoint__user_initial_stackheap()setupstack&heapresethandlerinitializestackpointersconfigureMMU/MPUsetupcache/enableTCM$Sub$$main()enablecaches&interrupts初始化棧的指針;---Amountofmemory(inbytes)allocatedforstacksLen_FIQ_StackEQU256Len_IRQ_StackEQU256…Offset_FIQ_StackEQU0Offset_IRQ_StackEQUOffset_FIQ_Stack+Len_FIQ_Stack…Reset_HandlerLDRr0,stack_base;locatedbyscatterfile;EntereachmodeinturnandsetupthestackpointerMSRCPSR_c,#Mode_FIQ:OR:I_Bit:OR:F_Bit;NointerruptsSUBsp,r0,#Offset_FIQ_StackMSRCPSR_c,#Mode_IRQ:OR:I_Bit:OR:F_Bit;NointerruptsSUBsp,r0,#Offset_IRQ_Stack

…;SystemmodestackissetuplastMSRCPSR_c,#Mode_SYS:OR:I_Bit:OR:F_Bit;NointerruptsSUBsp,r0,#Offset_SYS_Stack;SetupstacklimitifneededLDRr10,stack_limit;locatedbyscatterfile

局部存儲(chǔ)器設(shè)置run-time的存儲(chǔ)器必須在C庫(kù)初始化前定義如果你使用的ARM7芯片還有MMU/MPU,它必須設(shè)置;ROM/RAM的重新映射必須完成。TCM’s(Tightlycoupledmemory)如果有TCM,典型的必須使能它。請(qǐng)注意:在TCM使能之前,要屏蔽ROM在Cache打開之前要返回。在c庫(kù)初始化代碼運(yùn)行之后,如果cache被使能,可以避免與cache相關(guān)的問題;擴(kuò)展功能系統(tǒng)初始化代碼通常在進(jìn)入主應(yīng)用之前運(yùn)行當(dāng)然,resethandler不是一個(gè)適合使能中斷和使能caches地方。在resethandler最后應(yīng)該放一個(gè)C運(yùn)行庫(kù)初始化代碼EG。IMPORT__main B__main我們可使用$Sub和$Super功能來(lái)包裝符號(hào)externvoid$Super$$main(void);void$Sub$$main(void){cache_enable(); //enablescachesint_enable(); //enablesinterruptssys_to_usr_mode(); //changemode-seenextslide$Super$$main(); //callsoriginalmain()}相關(guān)描述可在ADS1.2LinkerandUtilitiesGuide-4.4章查閱到。運(yùn)行模式考慮主應(yīng)用程序運(yùn)行在何種模式是要考慮的重要問題。用戶模式(Usermode)是非特權(quán)模式(unprivilegedmode)-保護(hù)你的系統(tǒng)系統(tǒng)初始化代碼只能運(yùn)行在特權(quán)模式(privilegedmode)。需要執(zhí)行特權(quán)操作比如:使能中斷。如果你的應(yīng)用要運(yùn)行在管理模式,簡(jiǎn)單的在管理模式下退出你的resethandler就可。如果你想在用戶模式下運(yùn)行你的應(yīng)用,你需在$Sub$$main()改變?yōu)橛脩裟J疆?dāng)然,__user_initial_stackheap()必須有權(quán)使用你的應(yīng)用模式寄存器。解決辦法是在系統(tǒng)模式里退出resethandler所有C庫(kù)初始化代碼有權(quán)使用用戶寄存器,但是仍然可以執(zhí)行特權(quán)操作。Agenda 一個(gè)PC軟件的構(gòu)造

裁減標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板

復(fù)位和初始化

深層次的存儲(chǔ)器器映象考慮

編譯和調(diào)試IMAGE長(zhǎng)跳轉(zhuǎn)VeneersROM_LOAD0x0000{ROM_EXEC0x0000{*(+RO) }RAM0x80000000{farfunc.o(+RO)*(+RW,+ZI)}}/*main.c*/

intmain(void)

{

farfunc();

}/*farfunc.c*/

voidfarfunc(void);

{

:

}代碼段可被遠(yuǎn)距離分開放置(比BL的跳轉(zhuǎn)范圍還遠(yuǎn))鏈接器可自動(dòng)增加長(zhǎng)跳轉(zhuǎn)Veneers,遠(yuǎn)距離的函數(shù)可被成功調(diào)用。0x00000000

blVen$AA$L$$farfunc : :Ven$AA$L$$farfunc

ldrpc,[pc,#-4]

dcd0x80000000 : :0x80000000

: movpc,lr存儲(chǔ)器映射寄存器你可以使用scatterloading來(lái)放置外設(shè)寄存器的存儲(chǔ)器映射在文件中定義它e.g.timer_reg.c struct{ volatileunsignedreg1;/*timercontrol*/ volatileunsignedreg2;/*timervalue*/ }timer_reg;

在存儲(chǔ)器映射的請(qǐng)求地址上增加另外的可執(zhí)行區(qū)來(lái)放置他們:

LOAD_FLASH0x240000000x04000000 { : TIMER0x40000000UNINIT { timer_reg.o(+ZI) } : }

UNINIT

顯示在ZI段沒有被初始化為0。Stack和Heap區(qū)(1)你也可以在SCATTER文件中放置stack和heap在匯編原文件里定義stack和heap區(qū)

比如.stackheap.s這個(gè)空間直接保留一個(gè)為0的存儲(chǔ)器塊 AREAstack,DATA,NOINIT SPACE0x3000;Reservestackspace

AREAheap,DATA,NOINIT SPACE0x3000;Reserveheapspace ENDStack和Heap區(qū)(2)增加一個(gè)可執(zhí)行區(qū)來(lái)定位這個(gè)區(qū)域LOAD_FLASH0X240000000x04000000{ : STACK0x1000UNINIT;length=0x3000 {stackheap.o(stack);stack=0x4000to0x1000 } HEAP0x15000UNINIT;length=0x3000 {stackheap.o(heap);heap=0x15000to0x18000 } }Heap的基地址起始為0x15000.Stack的最大地址為0x4000.Stack和Heap區(qū)(3)鏈接器將產(chǎn)生一個(gè)為每個(gè)可執(zhí)行區(qū)的基地址和限制地址的符號(hào)指針在你的代碼中引入這些符號(hào) IMPORT ||Image$$STACK$$ZI$$Base|| IMPORT||Image$$STACK$$ZI$$Limit|| IMPORT||Image$$HEAP$$ZI$$Base|| IMPORT||Image$$HEAP$$ZI$$Limit|| stack_base DCD||Image$$STACK$$ZI$$Limit|| stack_limit DCD||Image$$STACK$$ZI$$Base|| heap_base DCD||Image$$HEAP$$ZI$$Base|| heap_limit DCD||Image$$HEAP$$ZI$$Limit||使用DCD指令為這些段命名__user_initial_stackheap()在resethandler,這個(gè)stack指針(r13)和stack限制值(r10)通常設(shè)置了,他們分別通過R1和R3作為參數(shù)傳遞給__user_initial_stackheap

IMPORT__use_two_region_memory EXPORT__user_initial_stackheap__user_initial_stackheap LDRr0,heap_base ;SBvaluesetupinresethandler LDRr2,heap_limit ;SLvaluesetupinresethandler MOVpc,lrStackHeap這個(gè)__user_initial_stackheap()例子實(shí)現(xiàn)了兩個(gè)存儲(chǔ)器區(qū)域模式。

必須引用

__use_two_region_memory,在這HEAP被檢查,它是HEAP的限制值,而不是STACK指針存儲(chǔ)器映射例子16bitRAM0x100000x180000x40000x0000Fast32bitRAMVectorTableStackExceptionHandlersRW&ZIHeapFlash0x240000000x28000000ResetHandlerROPeripherals0x40000000外設(shè)控制寄存器的地址映射直接在FLASH運(yùn)行的代碼大小16位RAM被用來(lái)保存數(shù)據(jù)和HEAP區(qū)一些緊急的代碼和數(shù)據(jù)可放在快速的RAM區(qū)SCATTER文件例子::16bitRAM0x10000{*(+RW,+ZI)}HEAP0x15000UNINIT{stackheap.o(heap)}

TIMER0x40000000UNINIT{timer_reg.o(+ZI)}}FLASH0x240000000x04000000{FLASH0x240000000x04000000{init.o(Init,+First)*(+RO)}32bitRAM0x0000{vectors.o(Vect,+First)handlers.o(+RO)}STACK0x1000UNINIT{stackheap.o(stack)} :這個(gè)scatter文件執(zhí)行上頁(yè)所顯示的存儲(chǔ)器映射。Agenda 一個(gè)PC軟件的構(gòu)造

裁減標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板

復(fù)位和初始化

深層次的存儲(chǔ)器器映象考慮

編譯和調(diào)試IMAGE不使用段的消除和程序的入口點(diǎn)在默認(rèn)的情況下,鏈接器將從最終的image文件中刪除一些從不使用的代碼段,或從未使用的數(shù)據(jù)段。要查看哪些段被刪除了,在鏈接時(shí)用:

‘-infounused’.為了確保不刪除重要的段(比如:中斷向量表):使用匯編指令entry標(biāo)示所有的入口點(diǎn)(c庫(kù)有一個(gè)入口點(diǎn):__main()),使用‘-entry’選擇其中一個(gè)入口點(diǎn)作為image的入口,否則,鏈接器將給警告:

Imagedoesnothaveanentrypoint.(Notspecifiedor

notsetduetomultiplechoices)在生成ROMmableimage使推薦使用下面的鏈接命令:

armlinkobj1.oobj2.o-scatterscatter.scf

-infounused-entry0x0-oprog.axf

輸出選項(xiàng)鏈接器產(chǎn)生ELF/DWARF2格式的映像文件,選擇適當(dāng)?shù)恼{(diào)試器下載調(diào)試為把elf映像文件轉(zhuǎn)為‘ROMmable’格式使用

fromelf,例如.:

fromelfimage.axf-bin-o

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論