(转)Cortex_m3的启动过程

[复制链接]
827|1
手机看帖
扫描二维码
随时随地手机跟帖
xiaoqizi|  楼主 | 2018-7-27 10:38 | 显示全部楼层 |阅读模式

一.arm的启动过程

arm的启动代码一般是用汇编写的,在堆栈建立以后才可以运行C代码,因为C函数调用需要把参数,函数返回地址入栈,堆栈没有建立不能运行C代码。



应用程序启动过程

应用程序启动过程:

1.映像入口地址,一般为0X00000000地址,也可以指定为其他的地址,硬件复位起来,从地址0x00000000处取指,地址0x00000000处放的复位服务函数的地址,就会进入复位服务函数。在复位函数里做一些系统的初始化,然后调用系统函数_main();

2._main 直接跳转到 __scatterload,__scatterload 执行代码和数据复制以及 ZI 数据的清零。根据分散加载文件,拷贝RW数据到RAM,在RAM空间里建立ZI的数据空间,建立运行时的映像存储器映射,然后跳转到 __rt_entry(运行时的入口)则负责初始化 C 库。还设置应用程序的栈和堆,初始化库函数及其静态数据。

3.这时应用程序的堆栈建立了,跳转到main()函数,运行用户代码。


二.  存储器映射的建立

1.编译链接生成的ELF文件


ELF文件格式

链接器根据输入节的属性在一个区内对它们进行排序。 具有相同属性的输入节在区内形成相邻块。链接生成的ELF文件里的数据节。

RO:包括代码和只读数据(.init  .text  .rodata)

RW:读写数据(.data)

ZI:未初始化的数据,在装载区不分配空间,执行区才分配空间。(.bss)


2. 映像的加载区和执行区

加载区: 根据映像加载到内存时所在的地址(即映像开始执行之前的位置)。

执行区: 映像执行时所在的地址。

根区:  加载区和执行区的地址相同。

加载区和执行区

一般下载到FLASH里的2进制文件就放在加载区,上图中的0X0000-0X4000空间。应用程序启动时,__scatterload函数根据分散加载文件把RW数据节拷贝到RAM空间,然后在RAM空间分配ZI数据节的空间。因为对RAM空间里数据的读写比FLASH快。一般把RW的数据拷贝到RAM。RO节的数据不做处理。这样运行时的存储器空间就建立起来了。


二.堆栈的设置

__user_initial_stackheap() 可用 C 或 ARM 汇编语言来编写。它必须返回以下参数:

• r0 中的堆基址;

• r1 中的栈基址;

• r2 中的堆限制(双区模型);

• r3 中的栈限制(双区模型)。

堆栈的模式有2种:单区模式,双区模式。

1.单区模型

默认情况下为单区模型,应用程序的堆和栈在同一存储器区中互相朝向对方增长,其中栈从地址 0x40000 向下增长,堆从地址 0x20000 向上增长。将相应的值加载到寄存器 r0 和 r1,然后返回。r2 和 r3 保持不变,因为在单区模型中不使用堆限制和栈限制。


EXPORT __user_initial_stackheap

__user_initial_stackheap

LDR r0, =0x20000 ;

LDR r1, =0x40000 ;

; r2 not used (HL)

; r3 not used (SL)

MOV pc, lr


2.双区模型

使用双区模型必须使用汇编命令 IMPORT 引入符号 __use_two_region_memory。将堆和栈分别放置在存储器不同的区中,__user_initial_stackheap() 建立的专用堆限制来检查堆。需要设置堆栈的长度。


汇编代码的实现,。栈从 0x40000 向0x20000 的限制向下增长。为使用该栈限制,所有使用此实现的模块必须进行编译以便进行软件栈检查。堆从 0x28000000 到 0x28080000 向上增长。

IMPORT __use_two_region_memory

EXPORT __user_initial_stackheap

__user_initial_stackheap

LDR r0, =0x28000000 ;HB

LDR r1, =0x40000 ;SB

LDR r2, =0x28080000 ;HL

LDR r3, =0x20000 ;SL

MOV pc, lr


ylslib| | 2018-7-30 14:19 | 显示全部楼层
楼主,你的图片好像都挂掉了。

使用特权

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

本版积分规则

71

主题

3810

帖子

3

粉丝