赞
踩
AT32F415裸机开发时,启动流程一般包含:上电->复位->取字(栈指针、PC的初始值)->复位向量执行->跳转到主函数执行程序。
1. 至于ARM芯片为何需要复位,这里不展开说明,感兴趣可以去找资料。
2.系统复位后以及处理器开始执行程序前, 处理器会从 CODE 存储器中读出前两个字。
从地址0x0000_0000处取出主栈指针( MSP)的初始值;从地址0x0000_0004处取出程序计数器( PC)的初始值, 这个值是复位向量, LSB必须是1。然后从这个值所对应的地址处取值。
3.在 AT32F415 中,可以将主闪存存储器、启动程序存储区或片上 SRAM 这三块存储器重映射到
0x0000_0000~0x07FF_FFFF 的 CODE 区,由 BOOT1 和 BOOT0 管脚来设定 CODE 从哪块存储器启动,当{BOOT1, BOOT0}=00/10 时, CODE 从主闪存存储器启动,当{BOOT1, BOOT0}=01 时, CODE从启动程序存储器启动,当{BOOT1, BOOT0}=11 时, CODE 从片上 SRAM 启动。系统复位后或从待机模式退出时, BOOT1 和 BOOT0 管脚值都会被重新锁存。
启动程序存储器中包含内嵌的 Bootloader 程序, 可提供 flash 编程功能, 通过 USART2 或 USB 接口对flash 进行重新编程;也可以提供通信协议栈等额外的固件,可被软件开发人员通过 API 调用。
图1 AT32F415的内存映射与启动位置说明
4.程序在FLASH和SRAM的空间分配
当使用keil进行单片机的开发时,运行一段程序后,在output输出框会看到如下图的结果。
图2 程序编译结果
其中,Compiler编译器,使用的版本是 V5.06,程序会先经过编译、后链接linking生成可执行的代码,如果要下载单片机的Flash上,还需要转换成二进制(bin)或者十六进制(hex)的文件。具体过程如下:
图3 keil的编译过程
值得注意的是,经过编译后,并不会给变量赋地址(.o文件),只有经过链接器链接后变量才有地址,链接的作用可以看做是便于管理而做的分类,在链接阶段起作用的是分散加载文件,分散加载文件用来描述生成映像文件时所需的信息,即通过分散加载文件指定ARM链接器在链接阶段如何分配Code、RO-data、RW-data、ZI-data的地址,只用使用了分散加载文件后,你程序的变量、函数等数据才会有地址,只有如此做,程序在运行时,才能根据分配的地址去下一步执行程序,分散加载文件后面会详细讲解,这里只初步了解一下就可以。经链接后代码分为Code、RO-data、RW-data、ZI-data四部分。接下来是老生常谈的问题,每个区都是干嘛的呢?
之前我一直在想的一个问题是我的局部变量存放在哪里,其实是这样的,局部变量只有在程序运行的过程中才会生成,当程序不运行,即将关闭单片机的电源后,是没有局部变量的。所以这就要涉及到程序的两种状态存储态和运行态。
图4 程序的存储态和运行态
存储态:向Flash中下载程序时,其实仅仅下载的是CODE+RO-data+RW-data的内容,意思就是说,在掉电情况下,Flash里面的内存仅包含CODE+RO-data+RW-data这三块。
图5 程序在用户Flash上的结构(存储态)
运行态:当上电后,程序运行时,首先程序会从特定的地址进行启动,启动时会将RW-data的数据加载到SRAM中(启用文件中有一段代码是干这件事的,说的在具体点是分散加载文件会做这件事,在默认情况下,keil中的链接器armlink工具(D:\Keil_v526\ARM\ARMCC\bin\armlink.exe)已经帮你做完了这件事),单片机的 RO区域不需要加载到 SRAM,内核直接从 FLASH 读取指令运行。那ZI-data的数据怎么办呢?对于初始值为0全局变量来说,因为要在Code区要调用该全局变量,所以肯定要对其进行描述,程序运行时就知道了,原来你是初始值为0的全局变量呀,然后分散加载文件就在SRAM中给它分配了一段固定区域的地址;对于局部变量来说, 会自动分配大小,不用我们管。RW-DATA+ZI-DATA就是程序运行总共会占用SRAM的长度,为什么说总共呢?因为当某一个函数运行完后,在这个函数内部的局部变量会被释放掉。
再次强调一下,堆空间与栈空间包含在ZI-data区的范围。
图6 程序的组成
通常,对于栈生长方向向下的单片机,其内存一般模型是:
图7 内存模型
根据AT32F415的内存映射图可知SRAM的开始地址是:0x20000000,而根据图2程序编译结果可以看到RW-data=360 ZI-data=7392.由图7可知栈顶地址 = 0x20000000 + RW-data + ZI-data = 0x20001e48,下面观察MDK中,地址0x0000_0000处取出主栈指针( MSP)的初始值:
图8 仿真观察到的内存值
可以看到MSP=0x20001e48,与计算结果吻合。PC=0x0800024d,表示复位中断的入口地址为0x0800024d(BOOT引脚设定程序从FLASH启动)。
下面是一段程序变量的位置:
图9 内存位置示例
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。