RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

memheap死機(jī)問題的分析與解決

冬至子 ? 來源:張世爭(zhēng) ? 作者:張世爭(zhēng) ? 2023-06-07 14:56 ? 次閱讀

驗(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 的方法

1.jpg

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ī)的信息

1.jpg

死機(jī)后,打印線程,發(fā)現(xiàn) idle 線程棧異常

1.jpg

開啟 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ù),依舊是異常的!

1.jpg

由于 開發(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 的定義

1.jpg

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)存。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RAM
    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
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    求解,rtthread內(nèi)存管理部分memheap使用問題討論

    rtthread中源碼這部分memheap我看官方文檔中都說的很模糊,也沒有做過多的解釋說明,這個(gè)對(duì)于新手去使用這部分功能十分不友好,這里我有幾點(diǎn)看法和大家交流下,也先挖個(gè)坑占個(gè)位置。1.內(nèi)存連續(xù)
    發(fā)表于 04-19 09:34

    講解使用memheap內(nèi)存管理算法對(duì)內(nèi)部RAM和片外的SDRAM進(jìn)行管理的方法

    if (ptr != RT_NULL) break;} } ... ... // 省去分析無關(guān)代碼 return ptr;}??分析上述源碼我們可以看到首先調(diào)用了 rt_memheap
    發(fā)表于 05-11 14:45

    請(qǐng)問rt_memheap_free引起的死機(jī)該如何解決呢?

    我使用了rtthread v4.0.4版本的內(nèi)核,并且開啟了RT_USING_MEMHEAP和RT_USING_MEMHEAP_AS_HEAP本來是將內(nèi)部ram和sdram合并成一個(gè)大的ram空間
    發(fā)表于 02-08 11:16

    rt_memheap_init初始化外部sram死機(jī)是何原因呢?

    的 //rt_memheap_init(&Strucmem,"memexram", rt_heap_exram,打開,即只要一初始化片外sram 就會(huì)死機(jī),我該如何查呢 ?其中,片外sram 使用的fsmc 驅(qū)動(dòng)
    發(fā)表于 02-20 15:09

    路由器死機(jī)掉線問題原因分析

    路由器死機(jī)掉線問題原因分析 今天,作者就對(duì)寬帶路由器死機(jī)掉線問題進(jìn)行客觀分析,看看到底是什么原因造成了這些問題。
    發(fā)表于 10-20 09:21 ?1117次閱讀

    手機(jī)死機(jī)的原因有哪些?

    手機(jī)死機(jī)的原因有哪些? 我們對(duì)電腦的死機(jī)藍(lán)屏都習(xí)以為常,死機(jī)以后無非就是熱啟或者是RESET,但是我們對(duì)手機(jī)的死機(jī)常常抱怨,
    發(fā)表于 10-26 16:32 ?4034次閱讀

    筆記本重啟/死機(jī) 五項(xiàng)分析以及對(duì)策

    筆記本重啟/死機(jī) 五項(xiàng)分析以及對(duì)策 電腦包括筆記本電腦重啟和死機(jī)故障,都是電腦維修過程中的熱點(diǎn)問題,其中牽涉到的問題也
    發(fā)表于 01-19 11:00 ?358次閱讀

    路由器死機(jī)的原因分析

      本文主要給大家總結(jié)了路由器死機(jī)的四大類主要原因,并且就針對(duì)不同的問題給出了不同的解答,相信看過此文會(huì)對(duì)你以后解決死機(jī)問題有所幫助。   路由器死機(jī)
    發(fā)表于 08-19 11:53 ?468次閱讀

    電腦死機(jī)問題分析

      從電腦出現(xiàn)至今就一直被死機(jī)伴隨著,幾乎沒有誰的電腦從不遭遇死機(jī)。在使用過程中,偶爾一次死機(jī)應(yīng)該算是正?,F(xiàn)象,如果經(jīng)常死機(jī),電腦就存在一定的問題了。那么,
    發(fā)表于 08-19 14:51 ?607次閱讀

    Linux系統(tǒng)死機(jī)的軟硬件問題分析

      系統(tǒng)出現(xiàn)死機(jī),一般分為兩種情況:一是硬件問題;二是軟件問題。   一、硬件問題   可以考慮分析以下幾點(diǎn):   1、不要超頻CPU,如果已經(jīng)超
    發(fā)表于 09-25 10:57 ?2219次閱讀

    工控機(jī)死機(jī)現(xiàn)象分析

    死機(jī)是工控機(jī)故障中較為常見的一種,同時(shí)它也是最令人頭疼的一種。因?yàn)槠涔收宵c(diǎn)可大可小,而且產(chǎn)生死機(jī)的原因有很多種,另外其故障現(xiàn)象也是多種多樣的,我們可以把故障現(xiàn)象總的歸為兩大類一一規(guī)律性死機(jī)和隨機(jī)性
    發(fā)表于 10-23 14:10 ?11次下載

    PLC死機(jī)的軟件或硬件原因分析

    plc運(yùn)行時(shí)可能會(huì)出現(xiàn)死機(jī)的情況,這給工業(yè)生產(chǎn)造成不可預(yù)估的損失,因此,首先要了解PLC死機(jī)的原因,針對(duì)原因進(jìn)行排查,軟件或硬件錯(cuò)誤都有可能導(dǎo)致PLC死機(jī)
    發(fā)表于 03-24 09:12 ?2948次閱讀

    RT-Thread 學(xué)習(xí)筆記:memheap 死機(jī)問題的分析與解決

    memheap 的功能實(shí)現(xiàn),并且了解到 memheap 支持多塊內(nèi)存(物理地址不連續(xù))的管理,當(dāng)開啟 memheap 后,rt_malloc 可以遍歷所有注冊(cè)過的 memheap 內(nèi)
    的頭像 發(fā)表于 05-29 18:05 ?1845次閱讀
    RT-Thread 學(xué)習(xí)筆記:<b class='flag-5'>memheap</b> <b class='flag-5'>死機(jī)</b>問題的<b class='flag-5'>分析</b>與解決

    變量位置不同會(huì)死機(jī)?郭天祥老師視頻的遺留問題分析答案

    在郭天祥老師視頻里有一個(gè)問題分享,是EXMC初始化里的一個(gè)變量定義和初始化位置不同會(huì)導(dǎo)致程序死機(jī),最終定位到程序是進(jìn)入hardfault死機(jī),但暫時(shí)沒有后續(xù)分析了,這里我們來繼續(xù)分析
    的頭像 發(fā)表于 02-26 09:12 ?361次閱讀
    變量位置不同會(huì)<b class='flag-5'>死機(jī)</b>?郭天祥老師視頻的遺留問題<b class='flag-5'>分析</b>答案

    Air780E/Air780EP/Air780EQ/Air201模塊遇到內(nèi)存死機(jī)如何分析

    Air780E/Air780EP/Air780EQ/Air201模塊遇到內(nèi)存死機(jī)如何分析簡(jiǎn)介本文檔適用于合宙Air780E、Air780EP、Air780EQ、Air201關(guān)聯(lián)文檔和使用工具:移芯
    的頭像 發(fā)表于 07-19 16:07 ?519次閱讀
    Air780E/Air780EP/Air780EQ/Air201模塊遇到內(nèi)存<b class='flag-5'>死機(jī)</b>如何<b class='flag-5'>分析</b>
    RM新时代网站-首页