IAR中cortex-m4啟動(dòng)流程分析
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 write to registers */ wdog_unlock(); /* Clear the WDOGEN bit to disable the watchdog */ WDOG_STCTRLH &= ~WDOG_STCTRLH_WDOGEN_MASK; - }
- void wdog_unlock(void)
- {
/* NOTE: DO NOT SINGLE STEP THROUGH THIS */ /* There are timing requirements for the execution of the unlock. If * you single step through the code you will cause the CPU to reset. */ /* This sequence must execute within 20 clock cycles, so disable * interrupts will keep the code atomic and ensure the timing. */ DisableInterrupts; /* Write 0xC520 to the unlock register */ WDOG_UNLOCK = 0xC520; /* Followed by 0xD928 to complete the unlock */ WDOG_UNLOCK = 0xD928; /* Re-enable interrupts now that 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 use in all of the copy loops */ 13 uint32 n; 14 /* Declare pointers for various data sections. These pointers 15 * are initialized using values pulled in from the linker file 16 */ 17 uint8 * data_ram, * data_rom, * data_rom_end; 18 uint8 * bss_start, * bss_end; 19 /* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */ 20 extern uint32 __VECTOR_TABLE[]; 21 extern uint32 __VECTOR_RAM[]; 22 /* Copy the vector table to RAM */ 23 if (__VECTOR_RAM != __VECTOR_TABLE) 24 { 25 for (n = 0; n < 0x410; n++) 26 __VECTOR_RAM[n] = __VECTOR_TABLE[n]; 27 } 28 /* Point the VTOR to the new copy of the vector table */ 29 write_vtor((uint32)__VECTOR_RAM); 30 /* Get the addresses for the .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 ROM to RAM */ 36 while (n--) 37 *data_ram++ = *data_rom++; 38 /* Get the addresses for the .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; 43 while(n--) 44 *bss_start++ = 0; 45 /* Get addresses for any code sections that need to be copied from ROM to RAM. 46 * The IAR tools have a predefined keyword that can be used to mark individual 47 * functions for execution from RAM. Add "__ramfunc" before the return type in 48 * the function prototype for any routines you need to execute 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 ROM to RAM */ 55 n = code_relocate_end - code_relocate; 56 while (n--) 57 *code_relocate_ram++ = *code_relocate++; 58 }
在IAR中,
上面代碼中,先是指定了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?。?。
后面的代碼是拷貝數(shù)據(jù)到RAM中,搭建好C語(yǔ)言運(yùn)行環(huán)境。
評(píng)論