打印
[牛人杂谈]

MCU在运行到main()之前都干了什么

[复制链接]
611|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
500days|  楼主 | 2016-11-24 18:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
很多ARM工程师想当然的以为,自己开发的应用程序,用AK100Pro仿真器下载进入调试,MCU的PC指针必定停留在main()函数的入口。但实际上,在运行到main()前,MCU还做了很多事情。这里以一个LPC1700的Keil工程为例说明。

  MCU上电复位后,通常会从一个固定的地址开始启动,比如ARM7复位后的入口地址为0x00000000;或者类似Cortex-M内核从中断向量表中取出入口地址,中断向量表的地址必须是固定的。

  LPC1700为Cortex-M3内核,所以启动时会从中断向量表(地址0x00000000)处取出入口地址和堆栈指针,分别加载到PC和SP中。

  入口地址处通常放的是芯片相关的启动代码。这部分代码要完成很多芯片初始化的动作,由于与特定型号芯片相关,所以不能随随便便地就用到别的型号芯片上。通常我们会使用官方提供的例程,然后以此为基础进行必要的修改。以下是LPC1700的初始化代码,所有硬件相关的初始化操作放在了SystemInit()函数中。


    SystemInit()完成的功能可以有:设置看门狗、外部存储器接口、内核时钟等等。当然,这些代码有些是可以放到后面的main()函数中完成,但有些则必须放在运行到__main之前完成。

  芯片初始化完成后,接下来是执行C运行环境的初始化。C环境的初始化主要包含两点:

  按照分散加载文件的配置,将相应的数据段和代码段拷贝到相关位置,将ZI段清零。通过这个功能可以将C代码中未指定初始化值的全局变量和静态变量对应的内存清零,然后将指定初始化的全局变量和静态变量对应的内存初始化。另外,如果有通过分散加载文件设置代码存储在Flash中,然后自动搬运到RAM中运行(该功能将在后续**中细讲),也会在该阶段完成这个自动搬运工作。

  之后是初始化C库,完成后才跳转到main()。

  以下是LPC1700工程的一段初始化代码,不同的工程配置,反汇编出来的结果略有不同。






  所以说,在main()运行前,MCU其实已经做了很多工作了。如果程序下载没有出现问题,但是就是跑不到main(),有可能不是仿真器的问题。是否会是main()之前的初始化操作异常?

沙发
稳稳の幸福| | 2016-11-24 21:50 | 只看该作者
运行了.s启动文件的配置工作。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

120

帖子

3

粉丝