打印
[应用相关]

基于STM32详解C语言内存分配

[复制链接]
472|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
micoccd|  楼主 | 2022-8-22 11:50 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
不说废话,先上示例代码

uint8_t num_byte[4];
uint32_t num_word;
const uint32_t num_word_const = 0x1234;
uint32_t *point_heap;
int main(void)
{
  uint8_t num_byte_stack;
  static uint8_t num_byte_static;
  
  point_heap = (uint32_t *)malloc(4);
  *point_heap = 0x3421;
  free(point_heap);
  
  num_byte_stack = 0x11;
  
#pragma section = "CSTACK"
  char *pbeginstk = __section_begin("CSTACK");
#pragma section = "HEAP"
  char *pbeginheap = __section_begin("HEAP");   
  
  printf("CSTACK addr is 0x%x\r\n",pbeginstk);
  printf("HEAP addr is 0x%x\r\n",pbeginheap);
  
  printf("num_byte addr is 0x%x\r\n",&num_byte);
  printf("num_word addr is 0x%x\r\n",&num_word);
  printf("num_word_const addr is 0x%x\r\n",&num_word_const);
  printf("point_heap addr is 0x%x\r\n",&point_heap);
  printf("point_heap is 0x%x\r\n",point_heap);
  printf("num_byte_stack addr is 0x%x\r\n",&num_byte_stack);
  printf("num_byte_static addr is 0x%x\r\n",&num_byte_static);
}
打印如下

STACK addr is 0x20000320
HEAP addr is 0x20000720
num_byte addr is 0x20000308
num_word addr is 0x2000030c
num_word_const addr is 0x8002a44
point_heap addr is 0x20000310
point_heap is 0x20000728
num_byte_stack addr is 0x200006f8
num_byte_static addr is 0x20000318
先说结论:
num_byte、num_word、num_byte_static和point_heap存储在内部RAM中。
num_byte_stack存贮在栈
point_heap申请到的内存在堆中
num_word_const在内部flash中
如果是有同学对这个了然于胸,可以出门左转了,如果有些同学有兴趣,可以进一步往下看。

使用特权

评论回复
沙发
micoccd|  楼主 | 2022-8-22 11:53 | 只看该作者
大小端
因为后面的内容涉及到大小端问题,这里先说下大小端问题。

大端(Big-endian):数据的高位字节存放在地址的低端低位字节存放在地址高端;

小端(Little-endian):数据的高位字节存放在地址的高端低位字节存放在地址低端;

例如:

数据0x12345678存储格式

大端格式

低地址<----0x12|0x34|0x56|0x78---->高地址

小端格式

低地址<----0x78|0x56|0x34|0x12---->高地址

其中的地址,一般由编译器分配,也可在程序中自行指定。从上表中,可以清晰的看到,大小端是以字节为单位进行数据储存的方式。大端通俗的理解就是赋值数从左自右;小端则是从右自左。

我们常用的X86结构是小端模式,而KEILC51则为大端模式。很多的ARM,DSP都为小端模式,本文使用的平台STM32F207就是小段模式。

使用特权

评论回复
板凳
micoccd|  楼主 | 2022-8-22 11:54 | 只看该作者
逐步分析
先说关于堆栈的问题,下面代码可以打印出IAR平台下STM32的堆栈起始位置。
#pragma section = "CSTACK"
  char *pbeginstk = __section_begin("CSTACK");
#pragma section = "HEAP"
  char *pbeginheap = __section_begin("HEAP");

打印的结果如下
STACK addr is 0x20000320
HEAP addr is 0x20000720

这个地址是否正确,我们可以在IARdebug时,使用Disassembly窗口查看。

关于堆栈大小问题,如下

可以查到栈的终止位置是0x20000720,堆的终止位置是0x20000920。注意:这里计算牵扯到大小端的问题。

通过计算:

栈的大小=0x20000720-0x20000320=0x400。

堆的大小=0x20000920-0x20000720=0x200。

这和我们在IAR中的堆栈配置是一样的。


使用特权

评论回复
地板
micoccd|  楼主 | 2022-8-22 11:55 | 只看该作者
接下来就先说一下分配在内存的变量。

通过打印看出,num_byte、num_word、num_byte_static和point_heap并不在堆栈中,它们存储在内部RAM中。

使用Disassembly窗口查看如下

这也验证了static关键字,在修饰函数内的局部变量时,这个变量将和全局变量一样存储在内部ram中。

同时也说明了,STM32内部分配内存时候,是先分配全局变量(和static修饰的局部变量),再分配栈,最后再分配堆的。



对于栈的内存分配,局部变量,也就是num_byte_stack是存储在栈的范围内。

num_byte_stack addr is 0x200006f8

它的地址空间在栈中。因为在代码中num_byte_stack =0x11;使用Disassembly窗口查看到对应的地址数值是0x11。

关于栈,再说一句,栈不仅仅保存了局部变量,它会在函数切换,中断发生时保存现场,保存ARM内核的寄存器,这些不是这篇文章的讨论重点,这里先挖个坑,等以后有空再写篇文章专门说说这个部分。

使用特权

评论回复
5
micoccd|  楼主 | 2022-8-22 11:55 | 只看该作者
堆的问题,简单来说:malloc申请的内存都在堆中。point_heap指针指向的内存地址就在堆的范围内。

point_heap is 0x20000728

代码中*point_heap= 0x3421;在Disassembly窗口查看到对应的地址数值是0x3421。

最后一个num_word_const,const修饰的变量是存储在内部flash中的,它的地址在内部flash范围内。

在代码中也有对应的赋值操作,constuint32_t num_word_const = 0x1234;在Disassembly窗口查看到对应的地址数值是0x1234。

使用特权

评论回复
6
七毛钱| | 2022-8-23 11:05 | 只看该作者
感谢大神的分享,学习一下

使用特权

评论回复
7
Uriah| | 2022-9-30 08:30 | 只看该作者

微探针技术都属于侵入型攻击

使用特权

评论回复
8
Bblythe| | 2022-9-30 11:29 | 只看该作者

极限情况下可以定义的变量可占 247 个字节

使用特权

评论回复
9
万图| | 2022-12-25 07:27 | 只看该作者

ART2固定使用PCLK时钟,只有开启和关闭的问题,不存在其它时钟源选择

使用特权

评论回复
10
帛灿灿| | 2022-12-25 10:26 | 只看该作者

清除与电镀动作都会在化学过程中完成

使用特权

评论回复
11
Bblythe| | 2022-12-25 11:29 | 只看该作者

极限情况下可以定义的变量可占 247 个字节

使用特权

评论回复
12
周半梅| | 2022-12-25 13:25 | 只看该作者

切割完了第四个字符之后,再依次扫描剩下的空间,直到所扫描的这一竖上的所有点的灰度值不全为0时,认为是字符的开始并依次扫描直到所扫描的这一竖上的所有点的灰度值全为0时认为是字符的结束。

使用特权

评论回复
13
Pulitzer| | 2022-12-25 14:28 | 只看该作者

不同的代码逻辑就代表了不同的策略

使用特权

评论回复
14
童雨竹| | 2022-12-25 16:24 | 只看该作者

累加寄存器存储运行的数据和运算后的数据。

使用特权

评论回复
15
Wordsworth| | 2022-12-25 17:27 | 只看该作者

确定好硬件原理图,硬件布线,最后才是软件的开发

使用特权

评论回复
16
huangcunxiake| | 2022-12-25 17:47 | 只看该作者
很少有人用内存时候使用 这个申请。

使用特权

评论回复
17
feiyinglala| | 2022-12-25 20:15 | 只看该作者
说的很细了楼主

使用特权

评论回复
18
Bowclad| | 2023-1-1 17:34 | 只看该作者
常用的ARM内核的都是小端存储吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

92

主题

549

帖子

1

粉丝