2016-08-05 48 views
0

我正在使用stm32 + rtos來實現基於spi flash的文件系統。對於freertos,我採用了heap_1實現。這是我創造我的任務。Freertos + STM32 - 帶malloc的線程內存溢出

osThreadDef(Task_Embedded, Task_VATEmbedded, osPriorityNormal, 0, 2500); 
    VATEmbeddedTaskHandle = osThreadCreate(osThread(Task_Embedded), NULL); 

我給該線程分配了10000字節的內存。

和在這個線程中。我試圖將數據寫入閃存。在最初的幾個稱爲成功的工作。但不知何故,當我嘗試更多寫作時,它會崩潰。

VATAPI_RESULT STM32SPIWriteSector(void *writebuf, uint8_t* SectorAddr, uint32_t buff_size){ 



    if(STM32SPIEraseSector(SectorAddr) == VAT_SUCCESS){ 
     DBGSTR("ERASE SECTOR - 0x%2x %2x %2x", SectorAddr[0], SectorAddr[1], SectorAddr[2]); 
    }else return VAT_UNKNOWN; 
    if(STM32SPIProgram_multiPage(writebuf, SectorAddr, buff_size) == VAT_SUCCESS){ 
     DBGSTR("WRTIE SECTOR SUCCESSFUL"); 
     return VAT_SUCCESS; 
    }else return VAT_UNKNOWN; 

    return VAT_UNKNOWN; 

} 

VATAPI_RESULT STM32SPIProgram_multiPage(uint8_t *writebuf, uint8_t *writeAddr, uint32_t buff_size){ 
    VATAPI_RESULT nres; 
    uint8_t tmpaddr[3] = {writeAddr[0], writeAddr[1], writeAddr[2]}; 
    uint8_t* sectorBuf = malloc(4096 * sizeof(uint8_t)); 
    uint8_t* pagebuf = malloc(255* sizeof(uint8_t)); 
    memset(&sectorBuf[0],0,4096); 
    memset(&pagebuf[0],0,255); 
    uint32_t i = 0, tmp_convert1, times = 0; 


    if(buff_size < Page_bufferSize) 
     times = 1; 
    else{ 
     times = buff_size/(Page_bufferSize-1); 
     if((times%(Page_bufferSize-1))!=0) 
      times++; 
    } 

    /* Note : According to winbond flash feature, the last bytes of every 256 bytes should be 0, so we need to plus one byte on every 256 bytes*/ 
    i = 0; 
    while(i < times){ 
     memset(&pagebuf[0], 0, Page_bufferSize - 1); 
     memcpy(&pagebuf[0], &writebuf[i*255], Page_bufferSize - 1); 
     memcpy(&sectorBuf[i*Page_bufferSize], &pagebuf[0], Page_bufferSize - 1); 
     sectorBuf[((i+1)*Page_bufferSize)-1] = 0; 
     i++; 
    } 

    i = 0; 
    while(i < times){ 
     if((nres=STM32SPIPageProgram(&sectorBuf[Page_bufferSize*i], &tmpaddr[0], Page_bufferSize)) != VAT_SUCCESS){ 
      DBGSTR("STM32SPIProgram_allData write data fail on %d times!",i); 
      free(sectorBuf); 
      free(pagebuf); 
      return nres; 
     } 
     tmp_convert1 = (tmpaddr[0]<<16 | tmpaddr[1]<<8 | tmpaddr[2]) + Page_bufferSize; 
     tmpaddr[0] = (tmp_convert1&0xFF0000) >> 16; 
     tmpaddr[1] = (tmp_convert1&0xFF00) >>8; 
     tmpaddr[2] = 0x00; 
     i++; 
    } 
    free(sectorBuf); 
    free(pagebuf); 
    return nres; 
} 

我打開調試器,現在看來似乎崩潰時,我在功能「STM32SPIProgram_multiPage」 malloced「sectorbuf」,什麼IM困惑的是,我做免費的記憶「的malloc」之後。有人有想法嗎?

臂無 - EABI尺寸 「RTOS.elf」 BSS十進制十六名
77564 988 100756 179308 2bc6c RTOS.elf

+0

哦。之前,我把「sectorBuf」和「pagebuf」作爲全局變量,然後所有的函數都運行良好。但如果我這樣做,它會消耗太多的內存。那爲什麼現在我用動態內存來代替。 – Pawan

+0

所以我認爲問題是由使用動態內存引起的。 – Pawan

+1

您是否爲malloc分配了堆內存(heap_1.c及其關聯的堆大小完全獨立於malloc) – Garf365

回答

0

閱讀
文本數據the man

內存管理

[...]

如果是動態創建的RTOS對象然後標準C庫malloc()和遊離()函數有時可以用於該目的,但是...

它們並不總是可用的在嵌入式系統中, 它們佔用有價值的代碼空間, 它們不是線程安全的,而 它們不是確定性的(執行此功能所花費的時間將不同於調用呼叫) ...所以比不需要替代的內存分配實施。 一個嵌入式/實時系統對另一個嵌入式/實時系統可能具有非常不同的RAM和時序要求 - 因此,單個RAM分配算法將只適用於一部分應用程序。

爲了解決這個問題,FreeRTOS將內存分配API保留在其可移植層中。便攜層位於實現核心RTOS功能的源文件之外,允許爲正在開發的實時系統提供適用於特定應用的實現。當RTOS內核需要RAM時,不是調用malloc(),而是調用pvPortMalloc()。當RAM被釋放時,RTOS內核調用vPortFree()而不是調用free()。

[...]

(重點煤礦。)

所以意思是,如果你直接使用mallocFreeRTOS是不能處理系統消耗堆功能。如果您選擇heap_3管理,那麼這是一個簡單的malloc包裝。

另請注意,您選擇的內存管理沒有免費功能。

heap_1.c

這是所有的最簡單的實現。 一旦分配完畢,它不允許釋放內存。儘管如此,heap_1.c適用於大量嵌入式應用程序。這是因爲很多嵌入式應用程序都會創建系統引導時所需的所有任務,隊列,信號量等,然後在程序的整個生命週期中使用所有這些對象(直到應用程序再次關閉或重新引導)。什麼都不會被刪除。 實現只是簡單地將單個數組細分爲更小的塊,並請求RAM。數組的總大小(堆的總大小)由configTOTAL_HEAP_SIZE設置 - 它在FreeRTOSConfig.h中定義。提供configAPPLICATION_ALLOCATED_HEAP FreeRTOSConfig.h配置常量以允許將堆放置在內存中的特定地址處。

xPortGetFreeHeapSize()API函數返回未分配的堆空間總量,允許優化configTOTAL_HEAP_SIZE設置。

的heap_1實現:

可以的,如果你的應用程序從不刪除任務,隊列,信號量,互斥等(這實際上涵蓋在FreeRTOS中被使用的大部分應用程序)中使用。 始終是確定性的(總是需要執行相同的時間)並且不會導致內存碎片。 非常簡單並且從靜態分配的數組中分配內存,這意味着它通常適用於不允許真正的動態內存分配的應用程序。

(重點煤礦)

旁註:你始終以檢查malloc返回值!= NULL

+0

這是什麼意思,我選擇的內存管理(heap_1.c)沒有空閒容量?這是否意味着如果我打電話malloc。我不能釋放內存部分? – Pawan

+0

不可以。使用'heap_1'內存管理時,您必須直接使用'pvPortMalloc()',而不是'malloc'。如果你正確使用'heap_1'函數,你將無法釋放堆分配的內存。 – LPs

+0

在FreeRTOS中,您擁有動態分配內存的抽象,併爲您提供5種不同的實現。第一個(heap_1)只授權malloc,但是當你調用free時,它什麼都不做(在許多嵌入式項目中很有用,它只爲一個任務分配一次內存並且永遠不會釋放它)。 heap_2稍微複雜一點,它可以釋放內存,但內存管理很差。 heap_3只是malloc和free的封裝。 heap_4和heap_5具有更復雜的內存管理,特別適用於空閒內存。在你的情況下,你必須選擇2最後一個,並使用'pvPortMalloc'和'pvPortFree' – Garf365