驗(yàn)證環(huán)境
NUCLEO-L476RG 開發(fā)板,板載 STM32L476RGT6(96K SARM1 + 32K SRAM2)
Win10 64 位
Keil MDK 5.36
RT-Thread 5.0.1 版本(2023-05-28 master 主線)
bsp : bsp\\stm32\\stm32l476-st-nucleo
功能描述
最近在研究 RT-Thread 內(nèi)存的管理,熟悉了一下 memheap 的功能實(shí)現(xiàn),并且了解到 memheap 支持多塊內(nèi)存(物理地址不連續(xù))的管理,當(dāng)開啟 memheap 后,rt_malloc 可以遍歷所有注冊(cè)過的 memheap 內(nèi)存塊,并且進(jìn)行 內(nèi)存的申請(qǐng)與釋放。
當(dāng)前 STM32L476RGT6 支持兩塊 SRAM,其中 SRAM1 96KB,還有一塊 SRAM2 32KB,SRAM2 默認(rèn)沒有使用,嘗試開啟 SRAM2
環(huán)境搭建
stm32l476-st-nucleo 開啟 memheap 的方法
stm32l476-st-nucleo 開啟 SRAM2 的方法
#define HEAP_SRAM2_BEGIN (0x10000000)
#define HEAP_SRAM2_SIZE (32 * 1024)
static struct rt_memheap memheap_sram2;
int system_sram2_init(void)
{
return rt_memheap_init(&memheap_sram2, "sram2", (void *)HEAP_SRAM2_BEGIN, (rt_size_t)HEAP_SRAM2_SIZE);
}
INIT_BOARD_EXPORT(system_sram2_init);
功能測(cè)試
寫兩個(gè)測(cè)試命令:一直申請(qǐng)內(nèi)存直到無法申請(qǐng)內(nèi)存,一直釋放所以申請(qǐng)的內(nèi)存,確認(rèn) rt_malloc 會(huì)自動(dòng)到新增加的 memheap SRAM2 中申請(qǐng)內(nèi)存
功能驗(yàn)證通過,但是遇到死機(jī)問題
測(cè)試的函數(shù)
void *user_alloc(rt_size_t size)
{
return rt_memheap_alloc(&memheap_sram2, size);
}
void user_free(void *ptr)
{
rt_memheap_free(ptr);
}
void user_alloc_test(void)
{
for (int i = 0; i < MEMHEAP_BLOCK_NUM; i++)
{
user_ptr[i] = user_alloc(500);
if (!user_ptr[i])
{
rt_kprintf("malloc failed, index = %d\\n", i);
return;
}
else
{
rt_kprintf("[%d] : 0x%08x\\n", i, user_ptr[i]);
}
}
}
MSH_CMD_EXPORT(user_alloc_test, user_alloc_test);
void user_free_test(void)
{
for (int i = 0; i < MEMHEAP_BLOCK_NUM; i++)
{
if (user_ptr[i])
{
rt_kprintf("[%d] : 0x%08x\\n", i, user_ptr[i]);
user_free(user_ptr[i]);
}
}
}
MSH_CMD_EXPORT(user_free_test, user_free_test);
死機(jī)的信息
死機(jī)后,打印線程,發(fā)現(xiàn) idle 線程棧異常
開啟 CmBacktrace 組件后,發(fā)現(xiàn)死機(jī)的問題不是固定的,申請(qǐng)申請(qǐng)一個(gè)小內(nèi)存,都會(huì)觸發(fā)異常
問題分析
idle 線程的結(jié)構(gòu)數(shù)據(jù)被破壞了,這就說明,內(nèi)存越界了,但是測(cè)試?yán)讨徽{(diào)用了 RT-Thread memheap 的 內(nèi)存申請(qǐng)與釋放 API,并沒有其他的操作
手動(dòng)申請(qǐng)一塊內(nèi)存,沒有觸發(fā)死機(jī), list thread 發(fā)現(xiàn),idle 線程的棧數(shù)據(jù),依舊是異常的!
由于 開發(fā)板可以 單步調(diào)試,所以經(jīng)過單步調(diào)試,加上分析,確認(rèn)內(nèi)存的范圍,各個(gè)線程棧的內(nèi)存范圍,發(fā)現(xiàn)了一個(gè)奇怪的問題: 申請(qǐng)的內(nèi)存偶爾會(huì)與線程棧的【靜態(tài)內(nèi)存】重疊
由于死機(jī)問題并不是必現(xiàn),但是 idle 線程棧數(shù)據(jù)異常是必現(xiàn)的。當(dāng)前懷疑 memheap 的內(nèi)存范圍設(shè)置存在問題,通過對(duì)比其他開發(fā)板的 bsp,發(fā)現(xiàn)了問題所在。
原來 bsp stm32l476-st-nucleo 系統(tǒng)的內(nèi)存 HEAP_BEGIN 設(shè)置有問題,直接設(shè)置的 第一塊內(nèi)存的起始地址:
#define STM32_SRAM1_START (0x20000000)
#define HEAP_BEGIN STM32_SRAM1_START
初步看上去好像沒有問題,其實(shí)RT-Thread 開機(jī)后,靜態(tài)的內(nèi)存數(shù)據(jù)、線程棧,依舊會(huì)占用一些內(nèi)存,也就是其實(shí)內(nèi)存地址,不能設(shè)置為 STM32_SRAM1_START,而是 【剩余內(nèi)存】
【剩余內(nèi)存】或者叫【空閑內(nèi)存】的獲取方法如下:
#if defined(__ARMCC_VERSION)
extern int Image$$
RW_IRAM1
ZI
Limit;
#define HEAP_BEGIN ((void *)&Image
RW_IRAM1
ZI
Limit)
#elif ICCARM
#pragma section="CSTACK"
#define HEAP_BEGIN (__segment_end("CSTACK"))
#else
extern int __bss_end;
#define HEAP_BEGIN ((void *)&__bss_end)
#endif
如在 Keil MDK5 上,是 #define HEAP_BEGIN ((void *)&Image
RW_IRAM1
ZI$$Limit), 也就是 SRAM1 的 剩余內(nèi)存作為系統(tǒng) 堆內(nèi)存使用,而不是 SRAM1 的全部?jī)?nèi)存作為 堆內(nèi)存使用
解決方法
如上,重新設(shè)置 HEAP_BEGIN 即可
編譯發(fā)現(xiàn) RW_IRAM1 不存在,需要修改鏈接文件:bsp\\stm32\\stm32l476-st-nucleo\\board\\linker_scripts\\link.sct,增加 RW_IRAM1 的定義
RW_IRAM1 0x20000000 0x00018000 { ; RW data
.ANY (+RW +ZI)
}
以上修改后,memheap 內(nèi)存測(cè)試通過,不再觸發(fā)死機(jī)
小結(jié)
memheap 使用起來還是比較的簡(jiǎn)單,可以通過設(shè)置 開啟 RT_USING_MEMHEAP_AUTO_BINDING,也就是 勾選 [*] Use all of memheap objects as heap,決定新增加的 memheap 的內(nèi)存是否參與系統(tǒng)常規(guī)的內(nèi)存管理,如 rt_malloc、rt_free
用戶可以單獨(dú)的實(shí)現(xiàn)自己的 memheap 內(nèi)存塊 alloc、free 函數(shù),這樣只操作特定的 memheap。
當(dāng)前的一個(gè)小缺點(diǎn):如果 memheap 內(nèi)存塊較多,超過2個(gè),如 RAM1、RAM2、RAM3,并且開啟了 [*] Use all of memheap objects as heap,想實(shí)現(xiàn) RAM1與 RAM2 作為系統(tǒng)通用內(nèi)存管理,RAM3 用戶專用內(nèi)存管理,那么當(dāng)前的 memheap 機(jī)制做不到,因?yàn)?rt_malloc 依舊會(huì)在 RAM1、RAM2 不能申請(qǐng)內(nèi)存時(shí),去 RAM3 申請(qǐng)內(nèi)存。
-
RAM
+關(guān)注
關(guān)注
8文章
1368瀏覽量
114640 -
SRAM芯片
+關(guān)注
關(guān)注
0文章
65瀏覽量
12059 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1285瀏覽量
40081 -
STM32L476
+關(guān)注
關(guān)注
0文章
7瀏覽量
3781
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論