0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

随笔、ch32v的堆内存最大化(动态创建堆内存)

冬至子 来源:初级踩坑仔 作者:初级踩坑仔 2023-10-13 14:39 次阅读

前言
前面说了我用的MRS IDE,它生成的模板工程,默认堆大小是4KB,可以到board.c里查看

1.jpg

如果都是动态创建的话,这肯定是不够用啊,多几个线程就用光了
所以我决定把堆分配搞到最大化,先看看RTT Studio的ch32v307模板是怎么做的

1.jpg

好吧,RTT Studio是16KB,可能是够了,但有点不满足,再看看RTT Studio的STM32模板是怎么做的

1.jpg

了解STM32堆栈分配的同学肯定一样就看出来了(不了解的也没关系,马上的ch32我会出手,笑),没错,这就是我要的堆内存最大化!把bss段结尾作为堆起始地址,
RAM的最高地址处作为堆结尾地址。

CH32V和STM32的链接脚本略有不同,CH32V的栈结尾是放在RAM最高地址处的,所以我们不能像STM32那么做。

但也只要略微修改一下就好,下面是我理解的修改过程和原理,嫌麻烦的可以直接到后面的实操部分。

理论部分

我们先下载一下MRS的模板工程到芯片,用free命令看看修改前的堆内存,方便对比(RTT Studio一样操作)

1.jpg

可以看到堆内存总大小:4072 B 已使用:2468 B 最大使用:2468 B
接着我们打开链接脚本Link.ld文件看看ch32v的各个段是怎么分配的

点开Link.ld(RTT Studio是link.lds),看看SECTIONS(段分配),鉴于篇幅有点大,我就把各个段做的事情删了(删掉的我会用……代替),仅保留待会我们要用的东西

/* 初始化段,程序的入口 _start 存放在该段 /
.init :{......} >FLASH AT>FLASH
/
存放中断向量表 /
.vector :{......} >FLASH AT>FLASH
/
代码段 */
.text :{......} >FLASH AT>FLASH
/ 我看不懂的段,反正都是>FLASH AT>FLASH /
......
/ 重头戏来了,RAM /
.data :
{
......
/ 这里这个__global_pointer我看不懂是干嘛的,有懂得前辈指导一下嘛 /
PROVIDE( __global_pointer$ = . + 0x800 );
......
/*这里的PROVIDE提供的符号,我们可以在C程序里以取地址的方式获得值,
*我们待会改堆起始地址和堆结束地址就要用到PROVIDE提供的符号
/
PROVIDE( _edata = .); /
_edata代表data段结尾地址 */
}>RAM AT>FLASH
/*RAM AT>FLASH含义
这里表示data段(已初始化的静态/全局变量)是从FLASH复制到RAM的(这个功能由启动文件 startup_ch32v30x.S完成),所以data段会占用镜像文件(FLASH空间) /
.bss :
{
......
PROVIDE( _sbss = .); /
_sbss代表bss段起始地址 /
......
/
_ebss代表bss段结尾地址 ,我们可以用它作为我们的堆起始地址,当然,后面也提供了另外的
符号_end,end 都是一样的 /
PROVIDE( _ebss = .);
} >RAM AT>FLASH
/*RAM AT>FLASH含义
*这里表示bss段(未初始化的静态/全局变量)是从FLASH复制到RAM的(这个功能由启动文件 startup_ch32v30x.S完成),但是未初始化的静态或全局变量没有初值,启动文件搬运的时候只要 从RAM划出一块内存全部填0就好,所以bss段不会占用镜像文件(FLASH空间) /
PROVIDE( _end = _ebss);/ 我刚刚提到的堆内存起始地址 /
PROVIDE( end = . );
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
{
/
堆结束 ORIGIN(RAM) + LENGTH(RAM) - __stack_size/stack
w我们用它来作为堆结束地址 /
PROVIDE( _heap_end = . );
. = ALIGN(4);
PROVIDE(_susrstack = . );/
栈底 ORIGIN(RAM) + LENGTH(RAM) - __stack_size */
. = . + __stack_size;/ 查看完整Link.ld会发现__stack_size=2048 /
PROVIDE( _eusrstack = .);
} >RAM

程序注释我写的比较详细,有需要的可以看看啊。由此我们可以得出通过这个ch32v链接脚本所得到的镜像文件(elf,bin,hex之类)结构和RAM分配情况,首先镜像文件结构(这里应该不够完整,少一些Header,符号表之类的,不是不写,是我也没完全了解。有知道的欢迎补充)

1.jpg

知道了RAM结构,接下来的事情就好办了,只要把堆起始地址改为link.ld提供的_ebss/_end /end就可以了,堆结束地址改为_heap_end/_susrstack。OK,理论部分结束,下面开始实操。

实操部分

打开board.c

我们先看看原始代码

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE (1024)
static uint32_t rt_heap[RT_HEAP_SIZE]; // heap default size: 4K(1024 * 4)
RT_WEAK void *rt_heap_begin_get(void)
{
return rt_heap;
}
RT_WEAK void *rt_heap_end_get(void)
{
return rt_heap + RT_HEAP_SIZE;
}
#endif

改为下面这个:

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
/* 最大堆大小开关*/
#define USING_MAX_HEAP_SIZE 1
#if (USING_MAX_HEAP_SIZE == 0)
#define RT_HEAP_SIZE (1024)
static uint32_t rt_heap[RT_HEAP_SIZE]; // heap default size: 4K(1024 * 4)
void *rt_heap_begin_get(void)
{
return rt_heap;
}
void *rt_heap_end_get(void)
{
return rt_heap + RT_HEAP_SIZE;
}
#else
void rt_heap_begin_get(void)
{
return HEAP_BEGIN;
}
void rt_heap_end_get(void)
{
return HEAP_END;
}
#endif /
END OF USING_MAX_HEAP_SIZE
/
#endif

打开board.h可以看到模板工程已经定义了HEAP_BEGIN和HEAP_END,

1.jpg

但是他这个不对,__stack_size的值应该以以取地址方式获得,而且SRAM_SIZE也被写成立64K,那如果我们后面修改ch32v的FLASH和RAM配置的话,还要多改一下这里,所以直接用我这个

extern int _ebss,_heap_end;
#define HEAP_BEGIN ((void *)&_ebss)
#define HEAP_END ((void *)&_heap_end)

修改完成后编译下载,使用free命令查看堆内存分配

1.jpg

堆内存总大小:61568 B 大约60KB了.
大功告成!(擦汗)RTT Studio一样的操作,大家自己搞搞就行了。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RAM
    RAM
    +关注

    关注

    8

    文章

    1332

    浏览量

    113944
  • STM32
    +关注

    关注

    2251

    文章

    10731

    浏览量

    350588
  • MRS
    MRS
    +关注

    关注

    0

    文章

    7

    浏览量

    7594
  • RTThread
    +关注

    关注

    7

    文章

    130

    浏览量

    40590
  • ch32v307
    +关注

    关注

    0

    文章

    14

    浏览量

    1709
收藏 人收藏

    评论

    相关推荐

    堆栈内存内存之间的区别

    编写有效的代码需要了解堆栈和内存,这使其成为学习编程的重要组成部分。不仅如此,新程序员或职场老手都应该完全熟悉堆栈内存内存之间的区别,
    发表于 08-07 12:23 466次阅读
    堆栈<b class='flag-5'>内存</b>和<b class='flag-5'>堆</b><b class='flag-5'>内存</b>之间的区别

    内存管理(中)

    内存管理(中) 欢迎研究ZigBee的朋友和我交流。。。
    发表于 08-11 19:16

    最大化内存使用率且保证波形细节分析

    最大化内存使用率且保证波形细节
    发表于 12-08 06:23

    【原创】内存的那些事

    组),内存则适用于开辟较大块的内存。栈内存由编译器分配和释放,内存由程序员分配和释放。前期回
    发表于 07-12 09:48

    关于RT-Thread的动态内存管理简析

    管理算法只能启用一个,但是提供给用户的接口完全相同。注意事项:内存管理为了满足多线程场景下的安全分配,考虑多线程间的互斥问题。因此,不要在中断服务程序中分配或释放动态内存块。否则,
    发表于 04-06 17:11

    RTT Studio ch32v307的内存最大化

    就看出来了(不了解的也没关系,马上的ch32我会出手,笑),没错,这就是我要的内存最大化!把bss段结尾作为堆起始地址,RAM的最高地址处作为
    发表于 02-07 11:55

    Java开发者必须了解的内存技术

    先来看一个 Demo:在 Demo 中分配内存用的是 allocateDirect 方法,但其内部调用的是 DirectByteBuffer,换言之,DirectByteBuffer 才是实际操作
    发表于 07-01 10:19 3692次阅读
    Java开发者必须了解的<b class='flag-5'>堆</b>外<b class='flag-5'>内存</b>技术

    两种常见的内存管理方法:内存

    magic被称为魔数,会被赋值为一个特殊的固定值,它表示了该内存块是管理器管理的内存块,可以在一定程度上检查错误的内存操作。例如,若这个区域被改写,magic的值被修改为了其它值,表
    的头像 发表于 05-31 17:13 1.3w次阅读
    两种常见的<b class='flag-5'>内存</b>管理方法:<b class='flag-5'>堆</b>和<b class='flag-5'>内存</b>池

    C语言内存与栈的笔记资料说明

    本文档的主要内容详细介绍的是C语言内存与栈的笔记资料说明说明了C语言中与栈的区别,哪些数据存放在,哪些存放在栈。
    发表于 02-14 08:00 3次下载
    C语言<b class='flag-5'>内存</b><b class='flag-5'>堆</b>与栈的笔记资料说明

    嵌入式操作系统FreeRTOS内存如何管理和

    嵌入式操作系统FreeRTOS内存管理和
    的头像 发表于 01-10 15:17 4414次阅读
    嵌入式操作系统FreeRTOS<b class='flag-5'>内存</b>如何管理和<b class='flag-5'>堆</b>

    什么是内存内存是如何分配的?

    在一般的编译系统中,内存的分配方向和栈内存是相反的。当栈内存从高地址向低地址增长的时候,内存
    的头像 发表于 07-05 17:58 9673次阅读

    什么是内存?存储方式是什么样的?

    的存储方式。 C 代码中动态申请内存的申请函数是 malloc ,常见的内存代码如下图所示: 因为malloc函数返回值是一个内存地址,所
    的头像 发表于 06-22 10:29 899次阅读
    什么是<b class='flag-5'>堆</b><b class='flag-5'>内存</b>?存储方式是什么样的?

    glibc导致的内存泄露的排查过程

    本文记录一次glibc导致的内存泄露的排查过程。
    的头像 发表于 09-01 09:43 487次阅读
    glibc导致的<b class='flag-5'>堆</b>外<b class='flag-5'>内存</b>泄露的排查过程

    程序内存分区中的与栈

    (Heap)与栈(Stack)是开发人员必须面对的两个概念,在理解这两个概念时,需要放到具体的场景下,因为不同场景下,与栈代表不同的含义。一般情况下,有两层含义: (1)程序内存布局场景下,
    的头像 发表于 11-11 16:21 567次阅读
    程序<b class='flag-5'>内存</b>分区中的<b class='flag-5'>堆</b>与栈

    jvm配置内存初始值参数

    JVM(Java Virtual Machine)是Java语言的运行环境,它通过解释字节码并执行相应的指令来运行Java程序。在JVM中,(Heap)是用于存储对象实例的内存区域。而在Java
    的头像 发表于 12-05 14:17 455次阅读