2016-08-05 47 views
0

Ich arbeite mit Stm32 + Rtos, um ein Dateisystem basierend auf Spi-Flash zu implementieren. Für Freertos habe ich die Implementierung von heap_1 übernommen. So erstelle ich meine Aufgabe.Freertos + STM32 - Thread-Speicherüberlauf mit malloc

Ich habe diesem Thread 10000 Bytes Speicher zugewiesen.

und in diesem Thread. Ich habe versucht, Daten in Flash zu schreiben. In den ersten paar Fällen hat es erfolgreich funktioniert. aber irgendwie stürzt es ab, wenn ich mehr Zeit des Schreibens versuchte.

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; 
} 

Ich öffne den Debugger und es scheint, wie es zum Absturz bringen, wenn ich „sectorbuf“ in Funktion „STM32SPIProgram_multiPage“ malloced, was Im verwirrt ist, dass ich nach „malloc“ frei, den Speicher hat. Hat jemand eine Idee?

Arm-none-EABI-size "RTOS.elf"
Textdaten bss dez hex Dateiname
77564 988 100756 179308 2bc6c RTOS.elf

+0

oh. Vorher habe ich "sectorBuf" und "pagebuf" als globale Variablen verwendet, dann funktionieren alle Funktionen gut. aber es verbrauchen zu viel RAM, wenn ich dies tue. Deshalb benutzte ich stattdessen dynamisches Gedächtnis. – Pawan

+0

Also ich denke, das Problem wird durch die Verwendung von dynamischem Speicher verursacht. – Pawan

+1

Haben Sie Speicher für Heap-Management von malloc zuweisen (Heap_1.c und die zugehörige Heap-Größe ist völlig unabhängig von Malloc) – Garf365

Antwort

0

Lese the man

Speicherverwaltung

[...]

Wenn RTOS Objekte werden dynamisch dann die Standard-C-Bibliothek malloc() und free() erstellt Funktionen manchmal für den Zweck verwendet werden können, aber ...

sie sind nicht immer verfügbar auf Embedded-Systemen, nehmen sie wertvollen Coderaum, sie sind nicht threadsicher, und sie sind nicht deterministisch (die Menge der Zeit, die zur Ausführung der Funktion genommen wird, unterscheidet sich von Call to Call) ... so häufiger als Es ist keine alternative Speicherzuordnungsimplementierung erforderlich. Ein Embedded/Echtzeit-System kann sehr unterschiedliche RAM- und Timing-Anforderungen haben - daher ist ein einzelner RAM-Allocation-Algorithmus immer nur für eine Teilmenge von Anwendungen geeignet.

Um dieses Problem zu umgehen, hält FreeRTOS die Speicherzuweisung API in seiner tragbaren Schicht. Die tragbare Schicht befindet sich außerhalb der Quelldateien, die die Kern-RTOS-Funktionalität implementieren, wodurch eine anwendungsspezifische Implementierung ermöglicht wird, die für das zu entwickelnde Echtzeitsystem geeignet ist. Wenn der RTOS-Kernel RAM benötigt, ruft er anstatt malloc() pvPortMalloc() auf. Wenn RAM freigegeben wird, ruft der RTOS-Kernel vPortFree() auf, anstatt free() aufzurufen.

[...]

(Hervorhebung von mir.)

So ist die Bedeutung, dass, wenn Sie direkt malloc verwenden, FreeRTOS nicht in der Lage ist, den Haufen durch das System verbraucht zu handhaben Funktion. Gleiches, wenn Sie heap_3 Management wählen, das ein einfacher malloc Wrapper ist.

Beachten Sie auch, dass die Speicherverwaltung, die Sie wählen, keine freie Kapazität hat.

heap_1.c

Dies ist die einfachste Umsetzung aller. Es ist nicht möglich, den Speicher freizugeben, sobald es zugewiesen wurde. Trotzdem eignet sich heap_1.c für eine große Anzahl von eingebetteten Anwendungen. Dies liegt daran, dass viele kleine und tief eingebettete Anwendungen alle Tasks, Warteschlangen, Semaphore usw. erstellen, die beim Systemstart erforderlich sind, und dann alle diese Objekte für die Lebensdauer des Programms verwenden (bis die Anwendung wieder ausgeschaltet oder neu gestartet wird). Nichts wird jemals gelöscht. Die Implementierung unterteilt einfach ein einzelnes Array in kleinere Blöcke, wenn RAM angefordert wird. Die Gesamtgröße des Arrays (die Gesamtgröße des Heapspeichers) wird durch configTOTAL_HEAP_SIZE festgelegt, das in FreeRTOSConfig.h definiert ist. Die Konfigurationskonstante configAPPLICATION_ALLOCATED_HEAP FreeRTOSConfig.h wird bereitgestellt, damit der Heapspeicher an einer bestimmten Adresse im Speicher platziert werden kann.

Die API-Funktion xPortGetFreeHeapSize() gibt den Gesamtbetrag des Heapspeichers zurück, der nicht zugewiesen ist, sodass die Einstellung configTOTAL_HEAP_SIZE optimiert werden kann.

Die heap_1 Umsetzung:

Kann nie löscht eine Aufgabe, Warteschlange, Semaphore, Mutex, usw. (die eigentlich deckt die meisten Anwendungen, bei denen FreeRTOS verwendet wird), wenn Ihre Anwendung verwendet werden. Ist immer deterministisch (benötigt immer dieselbe Ausführungszeit) und kann nicht zu einer Speicherfragmentierung führen. Ist sehr einfach und belegt Speicher von einem statisch zugewiesenen Array, was bedeutet, dass es oft für Anwendungen geeignet ist, die keine echte dynamische Speicherzuweisung zulassen.

(. Hervorhebung von mir)

Randbemerkung: Sie haben immer Check malloc Rückgabewert != NULL.

+0

Was bedeutet das, dass die Speicherverwaltung, die ich wähle (heap_1.c), keine freie Kapazität hat? heißt das, wenn ich malloc anrufe. Ich kann diesen Speicherabschnitt nicht freigeben? – Pawan

+0

Nr. Cose von 'heap_1' Speicherverwaltung verwenden Sie' pvPortMalloc() ', nicht' malloc' direkt. Wenn Sie die Funktion 'heap_1' richtig verwenden, können Sie keinen Speicher freigeben. – LPs

+0

In FreeRTOS haben Sie eine Abstraktion von dynamisch zugewiesenem Speicher und es bietet Ihnen 5 verschiedene Implementierungen. Der erste (heap_1) autorisiert nur malloc, aber wenn Sie kostenlos aufrufen, tut es nichts (nützlich in vielen eingebetteten Projekten, die nur einen Zeitspeicher für Aufgaben zuweisen und niemals freigeben). heap_2 ist ein wenig komplexer und bietet freien Speicher, hat aber eine schlechte Speicherverwaltung. heap_3 ist nur ein Wrapper für malloc und free. Heap_4 und Heap_5 haben eine komplexere Speicherverwaltung, speziell für freien Speicher. In Ihrem Fall müssen Sie einen der letzten 2 wählen und 'pvPortMalloc' und' pvPortFree' verwenden. – Garf365