简体   繁体   English

Freertos + STM32-使用malloc的线程内存溢出

[英]Freertos + STM32 - thread memory overflow with malloc

I'm working with stm32+rtos to implement a file system based on spi flash. 我正在与stm32 + rtos一起实现基于spi闪存的文件系统。 For freertos, I adopted heap_1 implementation. 对于freertos,我采用了heap_1实现。 This is how i create my task. 这就是我创建任务的方式。

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

I allocated 10000 bytes of memory to this thread. 我为此线程分配了10000字节的内存。

and in this thread. 并在此线程中。 I tried to write data into flash. 我试图将数据写入闪存。 In the first few called it worked successfully. 在最初的几个人中,它成功地工作了。 but somehow it crash when i tried more time of write. 但是当我尝试写更多时间时,它以某种方式崩溃。

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

I open the debugger and it seems like it crash when i malloced "sectorbuf" in function "STM32SPIProgram_multiPage", what Im confused is that i did free the memory after "malloc". 我打开调试器,当我在函数“ STM32SPIProgram_multiPage”中分配了“ sectorbuf”时,它似乎崩溃了,我感到困惑的是我确实在“ malloc”之后释放了内存。 anyone has idea about it? 有人对此有想法吗?

arm-none-eabi-size "RTOS.elf" 无臂大小的“ RTOS.elf”
text data bss dec hex filename 文本数据bss dec十六进制文件名
77564 988 100756 179308 2bc6c RTOS.elf 77564 988 100756 179308 2bc6c RTOS.elf

Reading the man 男人

Memory Management 内存管理

[...] [...]

If RTOS objects are created dynamically then the standard C library malloc() and free() functions can sometimes be used for the purpose, but ... 如果RTOS对象是动态创建的,则有时可以将标准C库malloc()和free()函数用于此目的,但是...

they are not always available on embedded systems, they take up valuable code space, they are not thread safe, and they are not deterministic (the amount of time taken to execute the function will differ from call to call) ... so more often than not an alternative memory allocation implementation is required. 它们并不总是在嵌入式系统上可用,它们占用了宝贵的代码空间,它们也不是线程安全的,并且它们也不是确定性的(执行函数所花费的时间因调用而异)……因此通常不需要替代的内存分配实现。 One embedded / real time system can have very different RAM and timing requirements to another - so a single RAM allocation algorithm will only ever be appropriate for a subset of applications. 一个嵌入式/实时系统可能具有与另一个系统不同的RAM和时序要求-因此,单个RAM分配算法仅适用于部分应用程序。

To get around this problem, FreeRTOS keeps the memory allocation API in its portable layer. 为了解决这个问题,FreeRTOS将内存分配API保留在其可移植层中。 The portable layer is outside of the source files that implement the core RTOS functionality, allowing an application specific implementation appropriate for the real time system being developed to be provided. 可移植层位于实现核心RTOS功能的源文件之外,从而允许提供适合于正在开发的实时系统的特定于应用程序的实现。 When the RTOS kernel requires RAM, instead of calling malloc(), it instead calls pvPortMalloc(). 当RTOS内核需要RAM时,它不调用malloc(),而是调用pvPortMalloc()。 When RAM is being freed, instead of calling free(), the RTOS kernel calls vPortFree(). 当释放RAM时,RTOS内核将调用vPortFree()而不是调用free()。

[...] [...]

(Emphasis mine.) (强调我的。)

So the meaning is that if you use directly malloc , FreeRTOS is not able to handle the heap consumed by the system function. 因此,含义是,如果您直接使用malloc ,则FreeRTOS无法处理系统功能消耗的堆。 Same if you choose heap_3 management that is a simple malloc wrapper. 如果选择作为简单malloc包装器的heap_3管理,则相同。

Take also note that the memory management you choose has no free capability. 另请注意,您选择的内存管理没有空闲功能。

heap_1.c heap_1.c

This is the simplest implementation of all. 这是所有方法中最简单的实现。 It does not permit memory to be freed once it has been allocated. 一旦分配了内存,就不允许释放内存 Despite this, heap_1.c is appropriate for a large number of embedded applications. 尽管如此,heap_1.c适用于大量嵌入式应用程序。 This is because many small and deeply embedded applications create all the tasks, queues, semaphores, etc. required when the system boots, and then use all of these objects for the lifetime of program (until the application is switched off again, or is rebooted). 这是因为许多小型且深度嵌入式的应用程序会在系统启动时创建所需的所有任务,队列,信号量等,然后在程序生命周期内使用所有这些对象(直到再次关闭该应用程序或重新启动该应用程序) )。 Nothing ever gets deleted. 什么都不会被删除。 The implementation simply subdivides a single array into smaller blocks as RAM is requested. 该实现仅在请求RAM时将单个阵列细分为较小的块。 The total size of the array (the total size of the heap) is set by configTOTAL_HEAP_SIZE - which is defined in FreeRTOSConfig.h. 数组的总大小(堆的总大小)由configTOTAL_HEAP_SIZE设置-在FreeRTOSConfig.h中定义。 The configAPPLICATION_ALLOCATED_HEAP FreeRTOSConfig.h configuration constant is provided to allow the heap to be placed at a specific address in memory. 提供了configAPPLICATION_ALLOCATED_HEAP FreeRTOSConfig.h配置常量,以允许将堆放置在内存中的特定地址处。

The xPortGetFreeHeapSize() API function returns the total amount of heap space that remains unallocated, allowing the configTOTAL_HEAP_SIZE setting to be optimised. xPortGetFreeHeapSize()API函数返回仍未分配的堆空间总量,从而可以优化configTOTAL_HEAP_SIZE设置。

The heap_1 implementation: heap_1实现:

Can be used if your application never deletes a task, queue, semaphore, mutex, etc. (which actually covers the majority of applications in which FreeRTOS gets used). 如果您的应用程序从不删除任务,队列,信号灯,互斥锁等(实际上涵盖了使用FreeRTOS的大多数应用程序),则可以使用。 Is always deterministic (always takes the same amount of time to execute) and cannot result in memory fragmentation. 始终是确定性的(总是花费相同的时间来执行),并且不会导致内存碎片。 Is very simple and allocated memory from a statically allocated array, meaning it is often suitable for use in applications that do not permit true dynamic memory allocation. 它是非常简单的,可以从静态分配的数组中分配内存,这意味着它通常适用于不允许真正的动态内存分配的应用程序。

(Emphasis mine.) (强调我的。)

Side note: You have always to check malloc return value != NULL . 旁注:您必须始终检查malloc返回值!= NULL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM