社区导航

 

搜索
查看: 186|回复: 0

[资料分享] keil main之前执行过程

[复制链接]

2542

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2019-9-17 21:15 | 显示全部楼层 |阅读模式

硬件复位后,第一步是执行复位处理程序,这个程序的入口在启动代码里(默认),摘录一段cortex-m3的复位处理入口代码:

  1. Reset_Handler   PROC        ;PROC等同于FUNCTION,表示一个函数的开始,与ENDP相对?  
  2.                 EXPORT  Reset_Handler             [WEAK]  
  3.         IMPORT  SystemInit  
  4.                 IMPORT  __main  
  5.         LDR     R0, =SystemInit  
  6.                 BLX     R0  
  7.                 LDR     R0, =__main  
  8.                 BX      R0  
  9.                 ENDP  

 
  1. Reset_Handler PROC ;PROC等同于FUNCTION,表示一个函数的开始,与ENDP相对?

  2. EXPORT Reset_Handler [WEAK]

  3. IMPORT SystemInit

  4. IMPORT __main

  5. LDR R0, =SystemInit

  6. BLX R0

  7. LDR R0, =__main

  8. BX R0

  9. ENDP

这里SystemInit函数是我自己用C代码写的硬件底层时钟初始化代码,这个可不算是keil mdk给代劳的.初始化堆栈指针、执行完用户定义的底层初始化代码后,发现接下来的代码是调用了__main函数,这里之所以有__main函数,是因为在C代码中定义了main函数,函数标签 main() 具有特殊含义。main() 函数的存在强制链接器链接到 __main 和 __rt_entry 中的初始化代码。

 

其中,__main函数执行代码和数据复制、解压缩以及 ZI 数据的零初始化。解释一下,C代码中,已经赋值的全局变量被放在RW属性的输入节中,这些变量的初值被keil mdk压缩后放到ROM或Flash中(RO属性输入节)。什么是赋值的全局变量呢?如果你在代码中这样定义一个全局变量:int nTimerCount=20;变量nTimerCount就是已经赋值的变量,如果是这样定义:int nTimerCount;变量nTimerCount就是一个非赋值的变量,keil默认将它放到属性为ZI的输入节。为什么要压缩呢?这是因为如果赋值变量较多,会占用较多的Flash存储空间,keil 默认用自己的压缩算法。这个“解压缩”就是将存放在RO输入区(一般为ROM或Flash)的变量初值,按照一定算法解压缩后,拷贝到相应RAM区。ZI数据清零是指将ZI区的变量所在的RAM区清零。使用 UNINIT 属性对执行区进行标记可避免 __main 对该区域中的 ZI 数据进行零初始化。这句话很重要,比如我有一些变量,保存一些重要信息,不希望复位后就被清零,这时就可以用分散加载文件定义一块UNINIT属性的区,将不希望零初始化的变量定义到这个区即可。

来源:EEWorld 微控制器 MCU板块,转载请附上链接


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 /6 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2019-10-14 11:31 , Processed in 0.077904 second(s), 16 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表