[CortexM0--stm32f0308]memory详细使用的实验

来源:互联网 发布:硕士论文数据库 编辑:程序博客网 时间:2024/05/19 17:09

问题描述

stm32f0308 discovery在Keil工具下编译链接,并download代码到IC中,在程序下载到IC,以及到程序实际运行时IC是如何使用其memory来实现具体的功能的呢,因此对该问题,做了些简单实验来观察。对于IC内部核心单元如何取指,译码等这里不做详细说明,仅从应用程序角度对其中的memory如何使用做简单尝试。

stm32f0308 memory说明

对几段要用到的memory地址进行下说明:0x0000 0000到0x0001 0000的64K byte空间是根据boot模式不同的Alias区间,0x0800 0000到0x0801 0000的64K byte空间是用户Flash区间,从0x2000 0000到0x2000 2000的8K byte空间是SRAM区间。

内部Flash实验

Flash中放了啥

从编译后的.map文件看,总ROM大小为1176byte,用Keil的Memory工具看到0x08000000往后大约1176byte有data,再往后均为FFFF了,看来用Flash download工具的作用就是将编译链接后生成的.bin下载到Flash当中了。这部分应当是通过Flash的写入接口来完成的。看来使用Keil的flash download算法,是有多少code size,就只会往Flash写入多少内容了,不过应当会首先擦除整个Flash空间吧,这个是可以在Keil工具中配置的,被擦除的Flash都会变为FFFFFFFF了。

Flash中到底放了啥

前面也还只是大概说明了烧写到Flash中的内容,而Flash中绝大部分放的都是Read only,可执行的code,那这1176 byte中的code都有些什么:
__Vectors_Size 0x000000c0
__Vectors 0x08000000
__Vectors_End 0x080000c0
__main 0x080000c1
_main_stk 0x080000c1
_main_scatterload 0x080000c5
__main_after_scatterload 0x080000c9
_main_clock 0x080000c9
_main_cpp_init 0x080000c9
_main_init 0x080000c9
__rt_final_cpp 0x080000d1
__rt_final_exit 0x080000d1
Reset_Handler 0x080000d5
ADC1_COMP_IRQHandler 0x080000e7
CEC_IRQHandler 0x080000e7
DMA1_Channel1_IRQHandler 0x080000e7
DMA1_Channel2_3_IRQHandler 0x080000e7
DMA1_Channel4_5_IRQHandler 0x080000e7
EXTI0_1_IRQHandler 0x080000e7
EXTI2_3_IRQHandler 0x080000e7
EXTI4_15_IRQHandler 0x080000e7
FLASH_IRQHandler 0x080000e7
I2C1_IRQHandler 0x080000e7
I2C2_IRQHandler 0x080000e7
PVD_IRQHandler 0x080000e7
RTC_IRQHandler 0x080000e7
SPI1_IRQHandler 0x080000e7
SPI2_IRQHandler 0x080000e7
TIM14_IRQHandler 0x080000e7
TIM15_IRQHandler 0x080000e7
TIM16_IRQHandler 0x080000e7
TIM17_IRQHandler 0x080000e7
TIM1_BRK_UP_TRG_COM_IRQHandler 0x080000e7
TIM1_CC_IRQHandler 0x080000e7
TIM2_IRQHandler 0x080000e7
TIM3_IRQHandler 0x080000e7
TIM6_DAC_IRQHandler 0x080000e7
TS_IRQHandler 0x080000e7
USART1_IRQHandler 0x080000e7
USART2_IRQHandler 0x080000e7
WWDG_IRQHandler 0x080000e7
__aeabi_uidiv 0x080000f1
__aeabi_uidivmod 0x080000f1
__scatterload 0x0800011d
__scatterload_rt2 0x0800011d
这样看就比较明了了,开始是vector table相关,紧接着应当是armlib提供的内部函数,用于在跳到用户main函数之前做一些初始化。至于那些IRQ handler这里实际没什么用,还是需要用户自己实现对应的handler函数的。

stm32f0308的physical map功能

从0x00000000往后大约1176 byte的data,与在0x08000000往后的一样,看来是stm32f0的memory map的作用。

SRAM实验

Read only和Read/Write的区别

在Keil的Memory工具中,对0x2000 0000及之后的SRAM区域,可以双击并修改RAM中的内容,而对0x0800 0000及0x0000 0000之后的内容双击时,无法更改,提示cannot access memory。而且在修改了SRAM的响应区域时,发现程序运行异常了,看来是动到栈了吧。对于SRAM和Flash的读写权限,显而易见的,对于MCU而言,SRAM是随机存储器,可读可写的,而Flash相当于ROM,只能读,存的代码指令就是只读的,CPU可以通过address直接access,存的数据就是const的,即只读数据,因此从Keil的memory工具可以看到Flash memory的所有数据(读取),但是却无法写入的。如果在程序中直接通过地址去写Flash memory的地址,属于对memory空间的非法操作,会导致hardfault。对Flash空间的数据写入必须要通过Flash peripheral接口才行的。

Stack和Heap到底在哪

接下来,要测试下打印出调用栈位置的代码。通过在main开始处定义一个局部结构体变量,然后用Keil的callstack看到该变量地址在0x200003F0的位置,那调用栈顶应当在这个位置,大约往低地址0x20000000有1K byte的空间。从startup.s文件看,定义的stack size是1K byte。但是还有0.5K byte的heap空间啊,还有.data和.bss空间,这栈具体是如何布置的呢?
对堆栈的继续实验:对于Flash中的内容,除非调用Flash的Write接口改变其数据,否则内部Flash中的数据是固定不会改变的。在reset IC后,启用Keil的debug功能,此时应当reset过程已经走完,会将Flash中.data搬移到SRAM中(.bss段是不需要搬移的,因为本来就没有初始数据,但是必须将它的空间给留出来),而且此时程序应当是跳到用户Entry处的main函数了,那这时候stack和heap其实都已经初始化好了。从链接后的.map文件看到,.data的大小有28 byte,.bss的大小有1028 byte,于是用Keil的memory查看,0x2000 0000开始的28 byte空间的确是有数据的了,从0x2000 001C开始后面全是0000 0000,这些0000 0000一直延续到0x2000 0420,数一下,从0x2000 0000到0x2000 0420总共是1056 byte。可见,从0x2000 0000开始,先放.data部分,紧接着放.bss部分。接着从0x2000 0420往后翻,开始一小段会是FFFF FFFF的内容,继续翻就看到有数据了,一直到接近0x2000 2000,再往下就提示cannot access memory。感觉调用栈是从.bss之后开始的,并向地址增大的方向生长的。是这样吗?所以这里还是先打个问号,要想想是否实验的方法有问题。

再看stack和heap

上面的实验方式没有问题,只是有些细节地方开始没有注意到。
SRAM中,的确从0x2000 0000开始先放.data内容,再放.bss,再接着是Heap区域,紧接着是Stack区域。不过,这里.bss其实并没有(不过具体是因为程序中没有未初始化的全局数据,还是因为.bss链接时就开始并没有分配空间?还是Stack本来就是一段未初始化的.bss数据?觉得应当是最后一点,待想办法验证下),所以其实call stack的栈顶指针是指向0x20000420的,然后从.data之后其实直接就是1K byte的stack区域了。这里最重要的一点,heap为什么没有了?因为这个应用程序没有用到动态分配,所以,被编译器优化直接去除掉了,这样,结合现在的原因就和上面观察的结果一致了。

0 0
原创粉丝点击