stm32f0308]memory详细使用的实验

问题描述

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_Size0x000000c0 __Vectors0x08000000 __Vectors_End0x080000c0 __main0x080000c1 _main_stk0x080000c1 _main_scatterload0x080000c5 __main_after_scatterload0x080000c9 _main_clock0x080000c9 _main_cpp_init0x080000c9 _main_init0x080000c9 __rt_final_cpp0x080000d1 __rt_final_exit0x080000d1 Reset_Handler0x080000d5 ADC1_COMP_IRQHandler0x080000e7 CEC_IRQHandler0x080000e7 DMA1_Channel1_IRQHandler0x080000e7 DMA1_Channel2_3_IRQHandler0x080000e7 DMA1_Channel4_5_IRQHandler0x080000e7 EXTI0_1_IRQHandler0x080000e7 EXTI2_3_IRQHandler0x080000e7 EXTI4_15_IRQHandler0x080000e7 FLASH_IRQHandler0x080000e7 I2C1_IRQHandler0x080000e7 I2C2_IRQHandler0x080000e7 PVD_IRQHandler0x080000e7 RTC_IRQHandler0x080000e7 SPI1_IRQHandler0x080000e7 SPI2_IRQHandler0x080000e7 TIM14_IRQHandler0x080000e7 TIM15_IRQHandler0x080000e7 TIM16_IRQHandler0x080000e7 TIM17_IRQHandler0x080000e7 TIM1_BRK_UP_TRG_COM_IRQHandler0x080000e7 TIM1_CC_IRQHandler0x080000e7 TIM2_IRQHandler0x080000e7 TIM3_IRQHandler0x080000e7 TIM6_DAC_IRQHandler0x080000e7 TS_IRQHandler0x080000e7 USART1_IRQHandler0x080000e7 USART2_IRQHandler0x080000e7 WWDG_IRQHandler0x080000e7 __aeabi_uidiv0x080000f1 __aeabi_uidivmod0x080000f1 __scatterload0x0800011d __scatterload_rt20x0800011d 这样看就比较明了了,开始是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为什么没有了?因为这个应用程序没有用到动态分配,所以,被编译器优化直接去除掉了,这样,结合现在的原因就和上面观察的结果一致了。

谁也不跟谁一辈子,有些事情没必要记在心上。

stm32f0308]memory详细使用的实验

相关文章:

你感兴趣的文章:

标签云: