今天我來講一講MCU開發(fā)中的一個(gè)棘手問題——內(nèi)存溢出,希望能幫到遇到該問題的同學(xué)們。
開發(fā)環(huán)境
SDK版本:SDK_2_6_13_FRDM-KW38
SDK下載地址:https://mcuxpresso.nxp.com
開發(fā)板:FRDM-KW38
IDE:IAR EmbeddedWorkbench for Arm version 8.50
演示代碼:https://github.com/N40E116/SDK_2_6_13_FRDM-KW38.git
本文總結(jié)了如下三類RAM使用情況的分析:
FreeRTOS RAM
CSTACK
動(dòng)態(tài)內(nèi)存分配
FreeRTOS RAM分析
因?yàn)槲覀兪褂玫氖菐?a href="http://www.brongaenegriffin.com/tags/RTOS/" target="_blank">RTOS的工程,所以這里先介紹一下FreeRTOS里stack和heap的管理和分析。
Task Stack分析
每個(gè)task的stack是獨(dú)立分配的,我們使用IAR的FreeRTOS分析插件對stack進(jìn)行分析,打開和使能方式如下:
以上方式針對的是在線debug時(shí)的分析查看,該方式查看信息較全面,可以在開發(fā)階段根據(jù)多數(shù)場景分配合適的stack,但是對于debugger離線后的溢出檢測則需要使用FreeRTOS自帶的stack異常檢測工具,打開方式如下,詳細(xì)信息請參考FreeRTOS- stacks and stack overflow checking
#define configCHECK_FOR_STACK_OVERFLOW 2 #if (configCHECK_FOR_STACK_OVERFLOW != 0) void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName) { panic(0,(uint32_t)vApplicationStackOverflowHook,0,0); } #endif
FreeRTOS Heap分析
FreeRTOS使用的heap通過如下宏定義,對于該Heap的溢出檢測可以使用FreeRTOS自帶的內(nèi)存分配失敗鉤子函數(shù)進(jìn)行檢測。
#define gTotalHeapSize_c 9000 #define configUSE_MALLOC_FAILED_HOOK 1
CSTACK分析
上面章節(jié)我們講了FreeRTOS中task占用stack的檢測方法,但是對于RTOS初始化前和中斷處理函數(shù)中用到的CSTACK該如何檢測呢?
IAR本身集成了CSTACK檢測功能,會(huì)顯示當(dāng)前棧的使用情況和最大棧深度,開發(fā)階段連接debugger,按如下方式設(shè)置后即可查看CSTACK信息。
如果系統(tǒng)產(chǎn)生了CSTACK溢出,我們該如何檢測哪里產(chǎn)生了這個(gè)溢出呢?這時(shí)我們可以使用IAR的數(shù)據(jù)斷點(diǎn)功能,將棧底位置寫入數(shù)據(jù)斷點(diǎn)的break位置,Access type改為Write,這樣只要棧底被修改了,即可產(chǎn)生斷點(diǎn),根據(jù)代碼break的位置,即可知道是哪里產(chǎn)生了CSTACK溢出。
一個(gè)快速獲得棧底位置的方法,如下圖所示,將鼠標(biāo)放到IAR的CSTACK的進(jìn)度條處即可顯示stack的使用范圍。
對于debugger離線后的CSTACK溢出檢測,我們可以通過初始化??臻g為一個(gè)固定值,例如在線分析時(shí)為0xcd,定時(shí)檢測棧底上的該值是否有被修改來檢測。
如下所示為在idle任務(wù)中進(jìn)入低功耗前增加棧底數(shù)據(jù)的檢測。
void check_overflow_cstack() { extern uint32_t CHECK_OVERFLOW_CSTACK_SIZE[]; uint32_t CHECK_OVERFLOW_CSTACK_END = *((uint32_t*)0UL) - (uint32_t)CHECK_OVERFLOW_CSTACK_SIZE; if(*(uint32_t*)CHECK_OVERFLOW_CSTACK_END != 0xcdcdcdcd) { panic(0,(uint32_t)check_overflow_cstack,0,0); } } void BOARD_EnterLowPowerCb(void) { check_overflow_cstack(); … }
另外鏈接文件MKW38A512xxx4_PD_connectivity_lp.icf需要增加如下定義:
define exported symbol CHECK_OVERFLOW_CSTACK_SIZE = __size_cstack__;
動(dòng)態(tài)內(nèi)存分配
SDK沒有使用標(biāo)準(zhǔn)庫的malloc函數(shù),定義__heap_size__為0,所以用戶不能使用malloc和free函數(shù)。但如果需要?jiǎng)討B(tài)申請內(nèi)存該如何操作呢?SDK的Framework里定義了一套簡化的內(nèi)存管理函數(shù)MEM_BufferAlloc()和MEM_BufferFree()。
配置文件中需要預(yù)先定義需要的數(shù)據(jù)塊大小和數(shù)量,內(nèi)存申請單元會(huì)從這些內(nèi)存塊中選取滿足大小要求的最小的數(shù)據(jù)塊作為MEM_BufferAlloc()的返回結(jié)果。
#define AppPoolsDetails_c _block_size_ 80 _number_of_blocks_ 7 _eol_ _block_size_ 248 _number_of_blocks_ 2 _eol_ _block_size_ 312 _number_of_blocks_ 1 _eol_ _block_size_ 392 _number_of_blocks_ 1 _eol_
當(dāng)然如果用戶使用了該內(nèi)存分配方法,則需要根據(jù)應(yīng)用情況,對應(yīng)地增加內(nèi)存池中的系數(shù)。另外可以使能如下宏定義,查看分析內(nèi)存分配是否合理,具體用法請參考應(yīng)用筆記:
MemoryPool Optimizer on MKW3xA/KW3xZ (nxp.com.cn)。
MEM_DEBUG,MEM_TRACKING,MEM_DEBUG_OUT_OF_MEMORY
以上是我總結(jié)的一些overflow的應(yīng)對策略,強(qiáng)烈建議大家在開發(fā)階段加上這些檢測措施,因?yàn)閮?nèi)存溢出會(huì)導(dǎo)致各種意想不到的結(jié)果,如果只跟著看到的異?,F(xiàn)象分析,往往會(huì)浪費(fèi)很多不必要的時(shí)間和精力,如果大家有其它應(yīng)對內(nèi)存溢出的方法,歡迎一起討論學(xué)習(xí)。
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17971瀏覽量
366615 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3122瀏覽量
75249 -
RTOS
+關(guān)注
關(guān)注
24文章
851瀏覽量
121154 -
SDK
+關(guān)注
關(guān)注
3文章
1077瀏覽量
49060 -
內(nèi)存溢出
+關(guān)注
關(guān)注
0文章
10瀏覽量
1344
原文標(biāo)題:三分鐘搞定MCU內(nèi)存溢出
文章出處:【微信號:pzh_mcu,微信公眾號:痞子衡嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
免費(fèi)三分鐘
三分鐘搞定NFC
職場啟示: 三分鐘碎片化
讓程序運(yùn)行三分鐘,停一分鐘,循環(huán)下去,直到設(shè)置停止循環(huán)的位置
三分鐘能做什么?三分鐘能讓我的iPhone6s重啟N次!
小米掃地機(jī)器人臺灣開售 三分鐘售罄
三分鐘概述8類常用元器件資料下載

三分鐘看懂工字型功率電感外觀破損的常見原因gujing

Brocade幫助Netzlink實(shí)現(xiàn)三分鐘云服務(wù)供應(yīng)

三分鐘實(shí)現(xiàn)MQTT協(xié)議網(wǎng)關(guān)串口連接三菱FX3UPLC上傳騰訊云

三分鐘了解飛創(chuàng)直線電機(jī)運(yùn)動(dòng)模組特點(diǎn)、選型及應(yīng)用-FCL系列

Node-RED初學(xué)者教程-三分鐘學(xué)習(xí)

評論