2016-08-05 2 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; 
} 

私は、デバッガを開いて、私は混乱してイムは、私が「malloc関数」の後に空きメモリをやったことが何であるかを、「STM32SPIProgram_multiPage」機能で「sectorbuf」をmallocさとき、それはクラッシュのように思えます。誰もそれについて考えている?

アームなし、EABIサイズ "RTOS.elf" 読書12月六角名
77564 988 100756 179308 2bc6c RTOS.elf

+0

oh。以前は、 "sectorBuf"と "pagebuf"をグローバル変数に設定していましたが、すべての関数がうまく機能していました。私がそうするなら、それはあまりにも多くのRAMを消費する。なぜ私は代わりにダイナミックメモリを使用したのですか? – Pawan

+0

私は問題がダイナミックメモリを使用することによって引き起こされると思います。 – Pawan

+1

ヒープ管理のためのメモリをmalloc(heap_1.cとそれに関連するヒープサイズはmallocから完全に独立しています)で割り当てました – Garf365

答えて

0

BSS
テキストデータthe man

メモリ管理

[...]

RTOSオブジェクトは、その後、動的に、標準Cライブラリのmalloc()と)(free関数は時々の目的に使用することができますが、...

彼らは常に利用できないを作成している場合 これらはスレッドセーフではなく、 は決定的ではありません(機能の実行に要する時間はコールごとに異なります) ...代わりのメモリ割り当ての実装は必要ではありません。 1つの埋め込み/リアルタイムシステムは、非常に異なるRAMとタイミング要件を別のものに持つことができます。したがって、単一のRAM割り当てアルゴリズムは、アプリケーションのサブセットにのみ適しています。

この問題を回避するため、FreeRTOSはメモリ割り当てAPIをポータブル層に保持します。ポータブル層は、コアRTOS機能を実装するソースファイルの外部にあり、開発中のリアルタイムシステムに適したアプリケーション固有の実装を提供することができます。 RTOSカーネルがmalloc()を呼び出す代わりにRAMを必要とする場合、代わりにpvPortMalloc()を呼び出します。 RAMが解放されると、free()を呼び出す代わりに、RTOSカーネルはvPortFree()を呼び出します。

[...]

(重点鉱山。)

ので意味は、あなたが直接mallocを使用する場合、FreeRTOSはシステムによって消費ヒープを扱うことができないということです関数。単純なmallocラッパーであるheap_3管理を選択した場合も同じです。

選択したメモリ管理に空き容量がないことにも注意してください。

heap_1.c

これは、すべての最も単純な実装です。 割り当てられたメモリは、が解放されるのを許可しません。それにもかかわらず、heap_1.cは多数の組み込みアプリケーションに適しています。これは、システムが起動するときに必要なすべてのタスク、キュー、セマフォーなどを作成した小さなアプリケーションや深く組み込まれたアプリケーションが多数存在するため、これらのオブジェクトをすべてプログラムのライフタイムに使用するからです(アプリケーションが再びオフになるか、 )。何も削除されません。 実装は、RAMが要求されるときに、単一の配列を小さなブロックに分割するだけです。配列の合計サイズ(ヒープの合計サイズ)は、FreeRTOSConfig.hで定義されているconfigTOTAL_HEAP_SIZEによって設定されます。 configAPPLICATION_ALLOCATED_HEAP FreeRTOSConfig.h構成定数は、メモリー内の特定のアドレスにヒープを配置できるようにするために提供されています。

xPortGetFreeHeapSize()API関数は、割り当てられていない残りのヒープスペースの合計量を返します。これにより、configTOTAL_HEAP_SIZE設定を最適化できます。

heap_1実装:アプリケーションが(実際にFreeRTOSが使用されますするアプリケーションの大部分をカバー)タスク、キュー、セマフォ、ミューテックス、などを削除することはありません場合

を使用することができます。 常に確定的です(実行には常に同じ時間がかかります)。メモリの断片化につながることはありません。 静的に割り当てられた配列から非常に単純かつ割り当てられたメモリです。つまり、真の動的メモリ割り当てを許可しないアプリケーションでの使用に適していることがよくあります。

(重点鉱山。)

サイドノート:あなたがチェックmalloc戻り値!= NULLに常に持ってい

+0

これは、私が選択したメモリ管理(heap_1.c)に空き容量がないことを意味しますか?私がmallocを呼び出すなら、それは意味します。私はそのメモリセクションを自由にすることはできませんか? – Pawan

+0

いいえ、 'heap_1'メモリ管理を使うには' malloc'ではなく 'pvPortMalloc()'を使わなければなりません。正しく 'heap_1'関数を使用する場合、ヒープ割り当てメモリを解放することはできません。 – LPs

+0

FreeRTOSには、動的に割り当てられたメモリが抽象化されており、5種類の実装が用意されています。最初のもの(heap_1)はmallocのみを許可しますが、フリーで呼び出すと何もしません(タスクのために1回だけのメモリを割り当て、それを解放しない多くの組み込みプロジェクトで有用です)。ヒープ2はもう少し複雑でフリーメモリですが、メモリ管理は貧弱です。 heap_3はmallocへのラッパーとフリーです。 heap_4とheap_5は、より複雑なメモリ管理、特に空きメモリの管理を行います。あなたの場合、2つのうちの1つを最後に選択し、 'pvPortMalloc'と' pvPortFree'を使用する必要があります。 – Garf365