C语言在STM32中的内存分配

发布时间:2024-01-25  

01前言


不说废话,先上示例代码



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

",pbeginstk);

  printf("HEAP addr is 0x%x

",pbeginheap);

  

  printf("num_byte addr is 0x%x

",&num_byte);

  printf("num_word addr is 0x%x

",&num_word);

  printf("num_word_const addr is 0x%x

",&num_word_const);

  printf("point_heap addr is 0x%x

",&point_heap);

  printf("point_heap is 0x%x

",point_heap);

  printf("num_byte_stack addr is 0x%x

",&num_byte_stack);

  printf("num_byte_static addr is 0x%x

",&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中。


如果是有同学对这个了然于胸,可以出门左转了,如果有些同学有兴趣,可以进一步往下看。


02大小端


因为后面的内容涉及到大小端问题,这里先说下大小端问题。


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


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


例如:


数据0x12345678存储格式


大端格式


低地址高地址


小端格式


低地址高地址


C语言在STM32中的内存分配

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


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


03逐步分析


如果有同学对这部分不是很熟悉,建议先看一下我之前的推文《C语言的内存分配》,先把C语言的堆栈,内存等概念先熟悉下。


先说关于堆栈的问题,下面代码可以打印出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窗口查看。


C语言在STM32中的内存分配

关于堆栈大小问题,如下


C语言在STM32中的内存分配

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


通过计算:


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


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


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


C语言在STM32中的内存分配

接下来就先说一下分配在内存的变量。


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


使用Disassembly窗口查看如下

C语言在STM32中的内存分配

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


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


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


num_byte_stack addr is 0x200006f8

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

C语言在STM32中的内存分配

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


堆的问题,简单来说:malloc申请的内存都在堆中。point_heap指针指向的内存地址就在堆的范围内。


point_heap is 0x20000728

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

C语言在STM32中的内存分配

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


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

C语言在STM32中的内存分配


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>