新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > IAR中cortex-m4啟動(dòng)流程分析

IAR中cortex-m4啟動(dòng)流程分析

作者: 時(shí)間:2016-11-25 來(lái)源:網(wǎng)絡(luò) 收藏


start函數(shù)中,首先執(zhí)行 wdog_disable()函數(shù)來(lái)禁用看門(mén)狗,然后調(diào)用 common_startup()函數(shù)初始化RAM(復(fù)制向量表、清零.bss段等,為C語(yǔ)言運(yùn)行環(huán)境做準(zhǔn)備),接著執(zhí)行sysinit()函數(shù)初始化芯片(時(shí)鐘、用到的外設(shè)等)。下面依次分析這3個(gè)函數(shù)。

①wdog_disable()

對(duì)系統(tǒng)的設(shè)定無(wú)非是對(duì)各個(gè)寄存器值的修改。wdog_disable()函數(shù)在wdog.c文件中
  • void wdog_disable(void)
  • {
  • /*First unlock the watchdog so that we can writetoregisters*/
  • wdog_unlock();
  • /*Clear the WDOGEN bittodisable the watchdog*/
  • WDOG_STCTRLH&=~WDOG_STCTRLH_WDOGEN_MASK;
  • }
  • void wdog_unlock(void)
  • {
  • /*NOTE:DONOTSINGLESTEPTHROUGH THIS*/
  • /*There are timing requirementsforthe execution of the unlock.If
  • *you singlestepthrough the code you will cause the CPUtoreset.
  • */
  • /*This sequence must execute within 20 clock cycles,so disable
  • *interrupts will keep the code atomicandensure the timing.
  • */
  • DisableInterrupts;
  • /*Write 0xC520tothe unlock register*/
  • WDOG_UNLOCK=0xC520;
  • /*Followed by 0xD928tocomplete the unlock*/
  • WDOG_UNLOCK=0xD928;
  • /*Re-enable interruptsnowthat we are done*/
  • EnableInterrupts;
  • }



禁用看門(mén)狗流程很簡(jiǎn)單:先是解鎖寄存器,然后更改看門(mén)狗寄存器里面的值來(lái)禁用看門(mén)狗。解鎖看門(mén)狗寄存器:向解鎖寄存器里連續(xù)寫(xiě)入0xC520和0xD928,兩次寫(xiě)入的時(shí)間必須小于20個(gè)時(shí)鐘周期。所以在解鎖過(guò)程中不能單步運(yùn)行,期間也不能被中斷打斷,解鎖函數(shù)是 wdog_unlock()。上面DisableInterrupts和EnableInterrupts已經(jīng)在arm_cm4.h中定義過(guò):

#define DisableInterrupts asm(" CPSID i");

#define EnableInterrupts asm(" CPSIE i");

解鎖看門(mén)狗寄存器后,向看門(mén)狗寄存器里寫(xiě)入適當(dāng)?shù)闹稻涂梢越每撮T(mén)狗了。


也就是把WDOG_STCTRLH 寄存器(地址是0x40052000)的第0位置0.



②common_startup

初始化RAM(復(fù)制向量表、清零.bss段等,為C語(yǔ)言運(yùn)行環(huán)境做準(zhǔn)備)。
  • 1/*File:startup.c*/
  • 2 #include"common.h"
  • 3 #pragma section=".data"
  • 4 #pragma section=".data_init"
  • 5 #pragma section=".bss"
  • 6 #pragma section="CodeRelocate"
  • 7 #pragma section="CodeRelocateRam"
  • 8/********************************************************************/
  • 9 void
  • 10 common_startup(void)
  • 11{
  • 12/*Declare a counter well useinall of the copy loops*/
  • 13 uint32 n;
  • 14/*Declare pointersforvarious data sections.These pointers
  • 15*are initialized using values pulledinfrom the linker file
  • 16*/
  • 17 uint8*data_ram,*data_rom,*data_rom_end;
  • 18 uint8*bss_start,*bss_end;
  • 19/*AddressesforVECTOR_TABLEandVECTOR_RAM come from the linker file*/
  • 20 extern uint32 __VECTOR_TABLE[];
  • 21 extern uint32 __VECTOR_RAM[];
  • 22/*Copy the vector tabletoRAM*/
  • 23if(__VECTOR_RAM!=__VECTOR_TABLE)
  • 24{
  • 25for(n=0;n<0x410;n++)
  • 26 __VECTOR_RAM[n]=__VECTOR_TABLE[n];
  • 27}
  • 28/*Point the VTORtothe new copy of the vector table*/
  • 29 write_vtor((uint32)__VECTOR_RAM);
  • 30/*Getthe addressesforthe.data section(initialized data section)*/
  • 31 data_ram=__section_begin(".data");
  • 32 data_rom=__section_begin(".data_init");
  • 33 data_rom_end=__section_end(".data_init");
  • 34 n=data_rom_end-data_rom;
  • 35/*Copy initialized data from ROMtoRAM*/
  • 36while(n--)
  • 37*data_ram++=*data_rom++;
  • 38/*Getthe addressesforthe.bss section(zero-initialized data)*/
  • 39 bss_start=__section_begin(".bss");
  • 40 bss_end=__section_end(".bss");
  • 41/*Clear the zero-initialized data section*/
  • 42 n=bss_end-bss_start;
  • 43while(n--)
  • 44*bss_start++=0;
  • 45/*Getaddressesforany code sections that needtobe copied from ROMtoRAM.
  • 46*The IAR tools have a predefined keyword that can be usedtomark individual
  • 47*functionsforexecution from RAM.Add"__ramfunc"before the return typein
  • 48*thefunctionprototypeforany routines you needtoexecute from RAM instead
  • 49*of ROM.ex:__ramfunc void foo(void);
  • 50*/
  • 51 uint8*code_relocate_ram=__section_begin("CodeRelocateRam");
  • 52 uint8*code_relocate=__section_begin("CodeRelocate");
  • 53 uint8*code_relocate_end=__section_end("CodeRelocate");
  • 54/*Copy functions from ROMtoRAM*/
  • 55 n=code_relocate_end-code_relocate;
  • 56while(n--)
  • 57*code_relocate_ram++=*code_relocate++;
  • 58}


在IAR中,#pragmasection="NAME" [align]用來(lái)在C語(yǔ)言中指定一個(gè)名稱是NAME的段,align指定對(duì)齊方式。指定的段可以被段操作符來(lái)引用,段操作符包括 __section_begin, __section_end, 和 __section_size.個(gè)人理解.date、.date_init和.bss應(yīng)該是IAR中保留的段名稱,.date代表數(shù)據(jù)段中的常量,.date_init代表數(shù)據(jù)段中已初始化的變量,.bss代表未初始化的變量(zero)。

上面代碼中,先是指定了5個(gè)不同名稱的段(前3個(gè)是保留段名稱,代表這些段是從這里開(kāi)始的),CodeRelocate和CodeRelocateRam是在*.icf文件中定義的塊(block):
define block CodeRelocate { section .textrw_init }; define block CodeRelocateRam { section .textrw };
quote:
The_
_ramfunc keyword makes a function execute in RAM. Two code
sections will be created: one for the RAM execution (.textrw), and one for the ROM initialization (.textrw_init).



外部變量引用
extern uint32 __VECTOR_TABLE[]; extern uint32 __VECTOR_RAM[];
來(lái)自IAR的鏈接文件(.icf),在.icf文件中已經(jīng)定義了變量 __VECTOR_TABLE 和 __VECTOR_RAM 其值都是0x1fff0000."Copy the vector table to RAM"這段代碼進(jìn)行判斷,如果向量表不在RAM中,則把向量表拷貝到RAM開(kāi)始的地址上,這里由于在RAM中調(diào)試,代碼是直接下載到RAM中的,所以不用拷貝。

向量表已經(jīng)在RAM中了,接下來(lái)要重定向向量表,以便在發(fā)生異常時(shí)到RAM中取得異常入口地址(默認(rèn)情況下是在0x0?。?。write_vtor((uint32)__VECTOR_RAM) 這個(gè)函數(shù)用來(lái)寫(xiě)向量表偏移寄存器(VTOR,地址0xE000_ED08),這里寫(xiě)入的是RAM起始地址0x1FFF0000。注意這個(gè)地址是有要求的,并不是所有地址都能作為向量表起始地址,0x1FFF0000滿足要求(這個(gè)要求就是:必須先求出系統(tǒng)中共有多少個(gè)向量,再把這個(gè)數(shù)字向上增大到是 2 的整次冪,而起始地址必須對(duì)齊到后者的邊界上。例如,如果一共有 32 個(gè)中斷,則共有 32+16(系統(tǒng)異常)=48個(gè)向量,向上增大到 2的整次冪后值為 64,因此地址地址必須能被 64*4=256整除,從而合法的起始地址可以是:0x0,0x100,0x200 等----參見(jiàn)ARM Contex-M3權(quán)威指南)。另外,如果向量表在RAM區(qū)(相對(duì)于code區(qū)),需把bit[29]置位,這里0x1FFF0000也滿足要求。

后面的代碼是拷貝數(shù)據(jù)到RAM中,搭建好C語(yǔ)言運(yùn)行環(huán)境。

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

關(guān)鍵詞: IARcortex-m4啟動(dòng)流

評(píng)論


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

關(guān)閉