当前位置:   article > 正文

STM32内存笔记_怎么查stm32 flash地址

怎么查stm32 flash地址

红叶何时落水

首先明确一个概念ROM与RAM的区别

ROM又被称为“只读存储器”,ROM所存数据,一般是装入整机前事先写好的,整机工作过程中只能读出,而不像随机存储器那样能快速地、方便地加以改写。ROM所存数据稳定,断电后所存数据也不会改变。

ROM是用于存放一些死数据,比如说代码编译后产生的机器码,以及一些只读变量(const)

这些数据只能被读取不能被改写,但是可以稳定保存。(flash可以动态写入一些数据)

RAM又被称作“随机存储器”,是与CPU直接交换数据的内部存储器,也叫主存(内存)。它可以随时读写,而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储媒介。

RAM就是代码运行时的可运行空间

还有一个概念存储器映射

stm32是一个32位系统,那么他的寻址空间便是2^32bytes = 2^(10+10+10+2) = 4GB的寻址空间。

注意是寻址空间,不是实际的硬件空间。就是说他最大可以有4GB的空间进行分配。

存储器映射是指把芯片中或芯片外的FLASH,RAM,外设,BOOTBLOCK等进行统一编址。即用地址来表示对象。这个地址绝大多数是由厂家规定好的,用户只能用而不能改。用户只能在挂外部RAM或FLASH的情况下可进行自定义。

STM32中flash起始地址为0X08000000, 结束地址为0x08000000+512k(ZET6)

SRAM起始地址为0x20000000,结束地址为0x20000000+64k(ZET6)

flash里面有code, const定义的常量(.text = code + RO),以及已经初始化的变量(RW)

SRAM里面有固定内存

已经初始化的变量+定义了但没有初始化的变量(RW + RI)

以及用于动态分配内存的固定内存stack与heap;

其中stack作为系统的栈,所有函数里面定义的局部变量都是占用stack的空间的,递归调用函数要注意栈溢出问题。如果在函数内部定义一个static,那么这个变量是属于RI或RW段的,不属于stack.static表明了这个变量只能有包含他的那个函数调用。

  1. #define Pa(s,x) printf("%s-address: %p\n\r", s, x)
  2. void adc_init(void)
  3. {
  4. Pa("ADC_arr", ADC_arr);
  5. u8 i;
  6. u8 n = 1;
  7. static u8 k = 2;
  8. Pa("i", &i);
  9. Pa("n", &n);
  10. Pa("k", &k);
  11. }

 ADC_arr是一个未初始化的数组,属于RI段

变量i与n是这个函数的局部变量,有stack为它分配内存,

注意再插入一个知识点,SRAM的地址是从0x20000000~0x20000000+64k的

那么从小到大存放的数据类型分别是RW,RI,heap,stack

这里面 ADC_arr和k属于RI区段

i,n是stack分配的c800为50k

为什么会如此靠后呢?原因是工程中使用了freertos,其中freertos使用自己的堆栈,而他的堆栈实际上是属于RI段

  1. #define configTOTAL_HEAP_SIZE ((size_t)(40*1024)) //系统所有总的堆大小
  2. static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];

它定义了一个40k大小的静态数组,用于给不同的任务分配堆栈空间。它也是属于RI段的

所以系统的堆栈地址在他后面,差不多50k的位置。

起始任务的地址为10d0,说明rtos的heap前面有4k杂七杂八的变量,就是我们定义的ADC_arr(2k)与e这些全局变量以及局部静态变量

所以stack在最后,递归调用次数多记得把stack设置的大一些

对于heap,如果我们不使用动态分配的话,就可以直接将其设置为0

如果我们想要动态分配内存时,就要为他设置足够的内存,可以使用malloc等系统函数调用

什么时候要用到内存的动态分配呢?

当你定义一个结构体指针后,想要给它赋值时,一定要先分配相应大小的内存(不分配,编译器不报错)。而且,如果你在函数里面进行这个操作的话,指针地址位于stack,但分配的内存属于heap,函数结束后,不会影响heap里面已经被分配的空间。所以,在初始化对象类型时,以及结构体时,如果直接申明结构体变量的话,它是属于stack的,会被销毁。使用指针定义后,再分配空间后,属于heap,只能手动销毁。

  1. u32 NotifyValue;
  2. u8 num = 0;
  3. ADC_setdata *adc_setdata;
  4. adc_setdata = (ADC_setdata* )pvPortMalloc(sizeof(adc_setdata));
  5. _new_adc adc_data[2];
  6. adc_data[0].Init = Init;
  7. adc_data[0].Init(&adc_data[0], 1, 100, 0);
  8. adc_data[1].Init = Init;
  9. adc_data[1].Init(&adc_data[1], 2, 10, 0);
  10. adc_setdata->length = 2;//fuck特莫的,用指针定义得特莫的先分配空间,特莫的
  11. adc_setdata->data = adc_data;
  12. Pa("adc_setdata", adc_setdata);
  13. Pa("adc_data", adc_data);

 buffer是一个系统heap动态分配的数组,差不多47k的位置,调用系统malloc

ADC_Control_handler是一个RTOS任务句柄

adc_setdata指向任务堆分配的空间,调用pvPortMalloc

adc_data是任务栈分配的局部变量,任务堵塞是,要入栈的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/56805
推荐阅读
相关标签
  

闽ICP备14008679号