微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > IAR中cortex-m4启动流程分析

IAR中cortex-m4启动流程分析

时间:11-25 来源:互联网 点击:
  • 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;
  • }


禁用看门狗流程很简单:先是解锁寄存器,然后更改看门狗寄存器里面的值来禁用看门狗。解锁看门狗寄存器:向解锁寄存器里连续写入0xC520和0xD928,两次写入的时间必须小于20个时钟周期。所以在解锁过程中不能单步运行,期间也不能被中断打断,解锁函数是 wdog_unlock()。上面DisableInterrupts和EnableInterrupts已经在arm_cm4.h中定义过:

#define DisableInterrupts asm(" CPSID i");

#define EnableInterrupts asm(" CPSIE i");

解锁看门狗寄存器后,向看门狗寄存器里写入适当的值就可以禁用看门狗了。

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

②common_startup

初始化RAM(复制向量表、清零.bss段等,为C语言运行环境做准备)。
  • 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;n0x410;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]用来在C语言中指定一个名称是NAME的段,align指定对齐方式。指定的段可以被段操作符来引用,段操作符包括 __section_begin, __section_end, 和 __section_size.个人理解.date、.date_init和.bss应该是IAR中保留的段名称,.date代表数据段中的常量,.date_init代表数据段中已初始化的变量,.bss代表未初始化的变量(zero)。

上面代码中,先是指定了5个不同名称的段(前3个是保留段名称,代表这些段是从这里开始的),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[];
来自IAR的链接文件(.icf),在.icf文件中已经定义了变量 __VECTOR_TABLE 和 __VECTOR_RAM 其值都是0x1fff0000."Copy the vector table to RAM"这段代码进行判断,如果向量表不在RAM中,则把向量表拷贝到RAM开始的地址上,这里由于在RAM中调试,代码是直接下载到RAM中的,所以不用拷贝。

向量表已经在RAM中了,接下来要重定向向量表,以便在发生异常时到RAM中取得异常入口地址(默认情况下是在0x0取)。write_vtor((uint32)__VECTOR_RAM) 这个函数用来写向量表偏移寄存器(VTOR,地址0xE000_ED08),这里写入的是RAM起始地址0x1FFF0000。注意这个地址是有要求的,并不是所有地址都能作为向量表起始地址,0x1FFF0000满足要求(这个要求就是:必须先求出系统中共有多少个向量,再把这个数字向上增大到是 2 的整次幂,而起始地址必须对齐到后者的边界上。例如,如果一共有 32 个中断,则共有 32+16(系统异常)=48个向量,向上增大到 2的整次幂后值为 64,因此地址地址必须能被 64*4=256整除,从而合法的起始地址可以是:0x0,0x100,0x200 等----参见ARM Contex-M3权威指南)。另外,如果向量表在RAM区(相对于code区),需把bit[29]置位,这里0x1FFF0000也满足要求。

后面的代码是拷贝数据到RAM中,搭建好C语言运行环境。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top