打印
[应用相关]

【转】ARM启动过程分析

[复制链接]
781|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
风萧寒|  楼主 | 2017-2-16 12:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
CMSIS 到底是什么

CMSIS的意思是Cortex Micro-controller Software Interface Standard,微控制器软件接口标准, 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层。CMSIS 可实现与处理器和外设之间的一致且简单的软件接口,从而简化软件的重用,缩短微控制器开发人员新手的学习过程,并缩短新设备的上市时间。


如何使用CMSIS,需要哪些文件?

以Freescale Kinetis L系列举例。
独立于编译器的文件:
● Cortex-M3内核及其设备文件(core_cm3.h + core_cm3.c)
─ 访问Cortex-M0内核及其设备:NVIC等
─ 访问Cortex-M0的CPU寄存器和内核外设的函数

● 微控制器专用头文件(device.h) - MKL25Z4.h
─ 指定中断号码(与启动文件一致)
─ 外设寄存器定义(寄存器的基地址和布局)
─ 控制微控制器其他特有的功能的函数(可选)

● 微控制器专用系统文件( system_device.c) – system_MKL25Z4.h + system_MKL25Z4 .c
─ 函数SystemInit,用来初始化微控制器
–函数 void SystemCoreClockUpdate (void); 用于获取内核时钟频率
─SystemCoreClock,该值代表系统时钟频率
─ 微控制器的其他功能(可选)

● 编译器启动代码(汇编或者C)( startup_device.s) - startup_MKL25Z4.s for Keil
─ 微控制器专用的中断处理程序列表(与头文件一致)



你可以对比的看.scf 和.map文件,.map文件就是依据.scf文件来进行加载域和执行域的确定的。

我们可以看到VECTOR_ROM和ER_m_text的两个加载域和执行域是一致的。

这个图是我网上找的,具体地址界限并不和上面的程序一致。


沙发
风萧寒|  楼主 | 2017-2-16 12:34 | 只看该作者

下面我把具体的启动流程列出来:

  • 复位状态后,CM4的第一件事就是读取下列两个 32位整数的值:
    (1)从地址0x0000,0000处取出 MSP 的初始值。
    (2)从地址0x0000,0004处取出 PC的初始值——这个值是复位向量,LSB 必须是1 。 然后从这个值所对应的地址处取指。

    注意,这与传统的ARM 架构不同——其实也和绝大多数的其它单片机不同。传统的RM 架构总是从 0 地址开始执行第一条指令。它们的 0 地址处总是一条跳转指令。在 CM3中,0 地址处提供 MSP 的初始值,然后就是向量表(向量表在以后还可以被移至其它位置)。

    CM3上电后的向量表
  • 在复位函数里做一些系统的初始化: MSP赋值,SystemInit
    arm的启动代码一般是用汇编写的,在堆栈建立以后才可以运行C代码,因为C函数调用需要把参数,函数返回地址入栈,堆栈没有建立是不能运行C代码的。
    这里的SystemInit虽然在.c文件里,但内部代码全是对寄存器的操作,本身也没有参数和返回值,所有编译出来全是代码段,没有变量什么的。所以不会因为堆栈还没有建立就不能执行。
  • 然后调用系统函数__main(); (IAR跳转到__iar_program_start)
  • _main 直接跳转到 __scatterload,__scatterload 执行代码和数据复制以及 ZI 数据的清零。根据分散加载文件,拷贝RW数据到RAM,在RAM空间里建立ZI的数据空间,建立运行时的映像存储器映射.
  • 然后跳转到 __rt_entry(运行时的入口)则负责初始化 C 库。还设置应用程序的栈和堆,初始化库函数及其静态数据。
  • 这时应用程序的堆栈建立了,跳转到main()函数,运行用户代码。


上面startup中的|Image$$ARM_LIB_STACK$$ZI$$Limit| 什么意思???

__Vectors 第一个DCD就是 |Image$$ARM_LIB_STACK$$ZI$$Limit|
这是什么意思呢?这时候可以求助KEIL的Help工具。

在Linker User Guide的7.1.4中讲解了如何在分散加载文件scatter中指定栈和堆。

当你在分散加载文件中定义了两个自定义的执行域ARM_LIB_HEAP和ARM_LIB_STACK,这会引起ARM的library去用 |Image$$ARM_LIB_STACK$$ZI$$Limit|的值来执行__user_setup_stackheap()函数。

|Image$$ARM_LIB_STACK$$ZI$$Limit|
的意思是Address of the byte beyond the end of the ZI output section in the execution region.
在执行域的ZI域后面初始化栈。


使用特权

评论回复
板凳
feelhyq| | 2017-2-16 12:45 | 只看该作者
make,学习了

使用特权

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

本版积分规则

68

主题

134

帖子

3

粉丝