IAR启动代码分析 - 干货

IAR在运行到主()函数之前,要运行一段启动代码来初初始化寄存器,中断向量表以及系统时钟的初始化。我们先来了解一下中断向量表,可以再自己的工作空间找到相应的启动文件,我的叫startup_stm32f412vx.s,我们只要了解两个重要的。

__vector_table
        DCD     sfe(CSTACK)
        DCD     Reset_Handler             ; Reset Handler

        DCD     NMI_Handler               ; NMI Handler
        DCD     HardFault_Handler         ; Hard Fault Handler
        DCD     MemManage_Handler         ; MPU Fault Handler
        DCD     BusFault_Handler          ; Bus Fault Handler
        DCD     UsageFault_Handler        ; Usage Fault Handler
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     0                         ; Reserved
        DCD     0
...............省略..........

首先我们了解“__vector_table”这个的含义,看一下此文件中的对这个的描述。

; The name "__vector_table" has special meaning for C-SPY:
; it is where the SP start value is found, and the NVIC vector
; table register (VTOR) is initialized to this address if != 0.
;

在stm32f412vx_flash.icf文件中是这个值(根据自己设定):

define symbol __ICFEDIT_intvec_start__ = 0x0800C000;

接下来在了解第一个向量CSTACK指针,第二个是复位地址Reset_Handler指针.CSTACK是在“stm32f412vx_flash.icf”文件定义的一个快用来存放栈数据,看下定义:

define symbol __ICFEDIT_size_cstack__ = 0x600;
define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };

SFE(CSTACK)代表取这个块的最后一个地址的下一个地址,因为栈有先进后出的特性,栈数据的存储是从下而上的,栈数据的读取是由上而下的。

第二个是单片机开始(复位)地址,Reset_Handler,我们先在IAR设置一下,把勾去掉,如图:

之后下载运行,界面如图:

系统跑到复位地址执行一些操作,来粗略解释下这个流程:

Reset_Handler
        LDR     R0, =SystemInit
        BLX     R0
        LDR     R0, =__iar_program_start
        BX      R0

线路1:表明执行的地址。

线路2:将SystemInit函数地址给R0寄存器

line3中:跳到R0寄存器保存的地址去执行(也就是执行SystemInit这个函数)

line4,line5同上。

所以单片机上电的顺序就是初始化SP,PC寄存器,接下来跳到PC寄存器指向的方向执行程序。顺着这个思路,如果你有好几个程序,在上电的时候通过外部触发初始化SP以及PC,就可以分别进入不同的程序。放个启动程序链接体验一下,点我

接下来去看SystemInit这个函数做了什么:

/**
  * @brief  Setup the microcontroller system
  *         Initialize the FPU setting, vector table location and External memory 
  *         configuration.
  * @param  None
  * @retval None
  */
void SystemInit(void)
{
  /* FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
  #endif
  /* Reset the RCC clock configuration to the default reset state ------------*/
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset CFGR register */
  RCC->CFGR = 0x00000000;

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x24003010;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Disable all interrupts */
  RCC->CIR = 0x00000000;

#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
  SystemInit_ExtMemCtl(); 
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */

  /* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}

本想到此结束的,还是在解释一波吧,首先是进行了FPU(Float Point Unit)的初始化,SCB-> CPACR(系统控制块 - >协处理器门禁控制寄存器)系统控制块的协处理器访问控制器,看下这个寄存器的样子。

位    CP10和CP11设置
00拒绝访问。任何访问都会产生使用错误(类型为NOCP - 无协处理器)
01只支持特权访问,非特权访问会产生使用错误。
10保留 - 结果无法预测
11全访问

下面就是RCC时钟的初始化以及内部闪存向量的重定位。

详情请参考此文章,点我!

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值