精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

堆內存總大?。?1568 B 大約60KB了.
大功告成!(擦汗)RTT Studio一樣的操作,大家自己搞搞就行了。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • RAM
    RAM
    +關注

    關注

    8

    文章

    1367

    瀏覽量

    114545
  • STM32
    +關注

    關注

    2266

    文章

    10876

    瀏覽量

    354931
  • MRS
    MRS
    +關注

    關注

    0

    文章

    7

    瀏覽量

    7623
  • RTThread
    +關注

    關注

    8

    文章

    132

    瀏覽量

    40812
  • ch32v307
    +關注

    關注

    0

    文章

    14

    瀏覽量

    1811
收藏 人收藏

    評論

    相關推薦

    堆棧內存內存之間的區別

    編寫有效的代碼需要了解堆棧和內存,這使其成為學習編程的重要組成部分。不僅如此,新程序員或職場老手都應該完全熟悉堆棧內存內存之間的區別,
    發表于 08-07 12:23 ?707次閱讀
    堆棧<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 ?3773次閱讀
    Java開發者必須了解的<b class='flag-5'>堆</b>外<b class='flag-5'>內存</b>技術

    兩種常見的內存管理方法:內存

    magic被稱為魔數,會被賦值為一個特殊的固定值,它表示了該內存塊是管理器管理的內存塊,可以在一定程度上檢查錯誤的內存操作。例如,若這個區域被改寫,magic的值被修改為了其它值,表
    的頭像 發表于 05-31 17:13 ?1.4w次閱讀
    兩種常見的<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 ?4648次閱讀
    嵌入式操作系統FreeRTOS<b class='flag-5'>內存</b>如何管理和<b class='flag-5'>堆</b>

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

    在一般的編譯系統中,內存的分配方向和棧內存是相反的。當棧內存從高地址向低地址增長的時候,內存
    的頭像 發表于 07-05 17:58 ?9920次閱讀

    什么是內存?存儲方式是什么樣的?

    的存儲方式。 C 代碼中動態申請內存的申請函數是 malloc ,常見的內存代碼如下圖所示: 因為malloc函數返回值是一個內存地址,所
    的頭像 發表于 06-22 10:29 ?1144次閱讀
    什么是<b class='flag-5'>堆</b><b class='flag-5'>內存</b>?存儲方式是什么樣的?

    程序內存分區中的與棧

    (Heap)與棧(Stack)是開發人員必須面對的兩個概念,在理解這兩個概念時,需要放到具體的場景下,因為不同場景下,與棧代表不同的含義。一般情況下,有兩層含義: (1)程序內存布局場景下,
    的頭像 發表于 11-11 16:21 ?728次閱讀
    程序<b class='flag-5'>內存</b>分區中的<b class='flag-5'>堆</b>與棧

    jvm配置內存初始值參數

    JVM(Java Virtual Machine)是Java語言的運行環境,它通過解釋字節碼并執行相應的指令來運行Java程序。在JVM中,(Heap)是用于存儲對象實例的內存區域。而在Java
    的頭像 發表于 12-05 14:17 ?750次閱讀

    如何使用SystemView的監控功能

    SystemView能夠監視應用程序如何使用動態存儲。這意味著,如果應用程序中使用了C或C++、自定義或RTOS提供的內存池對象,我們可以跟蹤這些對象的使用情況。SystemVie
    的頭像 發表于 08-09 18:07 ?715次閱讀
    如何使用SystemView的<b class='flag-5'>堆</b>監控功能