[转]STM32自定义stack和heap位置和大小 [复制链接]

本博主:下列文章仅作参考,涉及到CCM RAM和 DMA相关还是非常容易出问题的,仅仅作为参考。有驱动把栈作为DMA内存,所以极易出问题,性能提升多少暂且不谈,通用性还是不好。

 

http://www.stmcu.org.cn/module/forum/thread-615259-1-1.html

 

 

 

 

     Stack和heap是运行c运行环境比较重要的两个东西。默认的启动代码把他们是设立在sram里面的,那怎么把他们放在别的地方(比如外部sram)呢?这里用f407做例子,给大家介绍一下arm的c库推荐的标准做法。

 

  首先在启动程序startup_stm32f407xx.s里面把这两段代码全部注释掉。

 

220329ooumu85ywpzxza5b.pnguploading.4e448015.gif转存失败重新上传取消

2.png(20.83 KB, 下载次数: 2)

下载附件

2018-3-26 22:03 上传

 

220329fec193m96owsscww.pnguploading.4e448015.gif转存失败重新上传取消

1.png(23.27 KB, 下载次数: 3)

下载附件

2018-3-26 22:03 上传

 

  然后在向量表第一个字的位置要自己定义一个RAM地址。我这里是放在CCM里面。

220329srsgirxgq8uuvayx.pnguploading.4e448015.gif转存失败重新上传取消

4.png(20.47 KB, 下载次数: 11)

下载附件

2018-3-26 22:03 上传



 

  这里要说明一下,这里设置的stack指针地址是芯片启动以后的stack指针地址。在你进入c环境的时候,c运行库首先会重新初始化stack地址和heap空间。所以这个地址在c环境运行起来以后就没用了。如果启动汇编程序在调用_main之前没用到任何c语言函数,那这stack地址都不用设置。(默认的启动汇编调用_main之前是用调用了一个LDR  R0, =SystemInit,一开始的stack就是为能运行这个SystemInit设置的。)

       然后在链接选项里面设置为自定义链接脚本。

220329kg2k7fx49bnqxovg.pnguploading.4e448015.gif转存失败重新上传取消

3.png(32.69 KB, 下载次数: 10)

下载附件

2018-3-26 22:03 上传

 

  在链接脚本里面添加两个运行段。要注意的是这两个运行段范围不要与其他运行段重叠了。默认的链接脚本是sct文件,在mdk工程的Objects文件夹里。你可以在自动生成的sct基础上改。

220330nyxy88kyjg8y8te2.pnguploading.4e448015.gif转存失败重新上传取消

5.png(26.28 KB, 下载次数: 5)

下载附件

2018-3-26 22:03 上传

 

   这里stack还是设置在CCM的最后。stack顶是0x1001000,大小是0x400,Stack是从高地址往低地址增长的,所以是-0x400。heap设置在外部sram里面。特别要注意的是这里是heap和stack两块内存是分开的,需要在程序里加上编译控制。

220330fdbaa7bfb3di7stb.pnguploading.4e448015.gif转存失败重新上传取消

6.png(18.81 KB, 下载次数: 4)

下载附件

2018-3-26 22:03 上传

 

       __asm(".global __use_realtime_heap\n\t");是指用heap算法里面的一种复杂算法,适合需要malloc大块空间,或者需要反复malloc和free的情况下用。这个算法有内存碎片合并的功能。不加这一句就是用的功能简单比较快的算法,反复malloc和free是会产生内存碎片的。上面是ARM Compiler6的写法,ARM Compiler5是#pragma import(__use_realtime_heap)。

   如果你使用了默认的stack和heap合在一起的情况,那就可以不用这句__asm(".global __use_two_region_memory\n\t");。这种情况下链接脚本里直接定义一个ARM_LIB_STACKHEAP 运行段就可以了。上面是ARM Compiler6的写法,ARM Compiler5是#pragma import __use_two_region_memory。

   另外既然heap被放在外部sram里面,你当然要先把外部sram初始化好。一般都是在void SystemInit(void)里面初始化的,这个是在c环境被初始化(_main)之前调用的。

   这样就好了,测试一下malloc,返回的地址就是在外部sram里面。

 

   上面只是一种方法,C库的文档里说直接指定启动汇编里的__heap_base和__initial_sp的值也是可以的,但是我没有成功过。哪位有成功的经验的可以分享一下。

 

         最后还有一些我想说一下。

         malloc和free是标准c库的内管管理功能。实现代码都是经过各种工业标准认证的,长时间运行是安全的。既然是Arm公司提供的c库,那肯定是为了arm构架做过特别优化的。性能上也是有保障的。所以推荐需要内存管理的还是用库里的malloc和free比较好。

   某些国内开发板的教程说,标准c库的malloc非常不好。在内存管理上都是自己去写了程序。我看了一下他们的代码,就是最简单的一个链表实现。什么数据对齐,垃圾回收,碎片整理,错误处理都没有。这种代码做个教学演示可以,你如果用到生产上,那肯定就是出现各种莫名其妙的问题。

   

   以上如有错误的地方,敬请指出。

 

版权声明:本文为博主smallcsduck原创文章转载请注明出处 http://smallcsduck.blog.163.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值