赞
踩
红叶何时落水
首先明确一个概念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表明了这个变量只能有包含他的那个函数调用。
- #define Pa(s,x) printf("%s-address: %p\n\r", s, x)
- void adc_init(void)
- {
- Pa("ADC_arr", ADC_arr);
- u8 i;
- u8 n = 1;
- static u8 k = 2;
- Pa("i", &i);
- Pa("n", &n);
- Pa("k", &k);
- }
-
-
-

ADC_arr是一个未初始化的数组,属于RI段
变量i与n是这个函数的局部变量,有stack为它分配内存,
注意再插入一个知识点,SRAM的地址是从0x20000000~0x20000000+64k的
这里面 ADC_arr和k属于RI区段
i,n是stack分配的c800为50k
为什么会如此靠后呢?原因是工程中使用了freertos,其中freertos使用自己的堆栈,而他的堆栈实际上是属于RI段
- #define configTOTAL_HEAP_SIZE ((size_t)(40*1024)) //系统所有总的堆大小
- 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,只能手动销毁。
- u32 NotifyValue;
- u8 num = 0;
- ADC_setdata *adc_setdata;
- adc_setdata = (ADC_setdata* )pvPortMalloc(sizeof(adc_setdata));
- _new_adc adc_data[2];
- adc_data[0].Init = Init;
- adc_data[0].Init(&adc_data[0], 1, 100, 0);
- adc_data[1].Init = Init;
- adc_data[1].Init(&adc_data[1], 2, 10, 0);
- adc_setdata->length = 2;//fuck特莫的,用指针定义得特莫的先分配空间,特莫的
- adc_setdata->data = adc_data;
- Pa("adc_setdata", adc_setdata);
- Pa("adc_data", adc_data);

buffer是一个系统heap动态分配的数组,差不多47k的位置,调用系统malloc
ADC_Control_handler是一个RTOS任务句柄
adc_setdata指向任务堆分配的空间,调用pvPortMalloc
adc_data是任务栈分配的局部变量,任务堵塞是,要入栈的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。