前言
前面說了我用的MRS IDE,它生成的模板工程,默認堆大小是4KB,可以到board.c里查看
如果都是動態(tài)創(chuàng)建的話,這肯定是不夠用啊,多幾個線程就用光了
所以我決定把堆分配搞到最大化,先看看RTT Studio的ch32v307模板是怎么做的
好吧,RTT Studio是16KB,可能是夠了,但有點不滿足,再看看RTT Studio的STM32模板是怎么做的
了解STM32堆棧分配的同學肯定一樣就看出來了(不了解的也沒關系,馬上的ch32我會出手,笑),沒錯,這就是我要的堆內存最大化!把bss段結尾作為堆起始地址,
RAM的最高地址處作為堆結尾地址。
CH32V和STM32的鏈接腳本略有不同,CH32V的棧結尾是放在RAM最高地址處的,所以我們不能像STM32那么做。
但也只要略微修改一下就好,下面是我理解的修改過程和原理,嫌麻煩的可以直接到后面的實操部分。
理論部分
我們先下載一下MRS的模板工程到芯片,用free命令看看修改前的堆內存,方便對比(RTT Studio一樣操作)
可以看到堆內存總大小: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段(已初始化的靜態(tài)/全局變量)是從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段(未初始化的靜態(tài)/全局變量)是從FLASH復制到RAM的(這個功能由啟動文件 startup_ch32v30x.S完成),但是未初始化的靜態(tài)或全局變量沒有初值,啟動文件搬運的時候只要 從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會發(fā)現__stack_size=2048 /
PROVIDE( _eusrstack = .);
} >RAM
程序注釋我寫的比較詳細,有需要的可以看看啊。由此我們可以得出通過這個ch32v鏈接腳本所得到的鏡像文件(elf,bin,hex之類)結構和RAM分配情況,首先鏡像文件結構(這里應該不夠完整,少一些Header,符號表之類的,不是不寫,是我也沒完全了解。有知道的歡迎補充)
知道了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,
但是他這個不對,__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命令查看堆內存分配
堆內存總大小:61568 B 大約60KB了.
大功告成!(擦汗)RTT Studio一樣的操作,大家自己搞搞就行了。
-
RAM
+關注
關注
8文章
1368瀏覽量
114641 -
STM32
+關注
關注
2270文章
10895瀏覽量
355743 -
MRS
+關注
關注
0文章
7瀏覽量
7625 -
RTThread
+關注
關注
8文章
132瀏覽量
40861 -
ch32v307
+關注
關注
0文章
14瀏覽量
1833
發(fā)布評論請先 登錄
相關推薦
評論