STM32F4在外部RAM中运行FreeRTOS [英] STM32F4 running FreeRTOS in external RAM

查看:2285
本文介绍了STM32F4在外部RAM中运行FreeRTOS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在工作中我们有一个论文项目,那些人正试图让外部RAM为STM32F417 MCU工作。
这个项目正在尝试一些真正耗费资源,内部RAM不够的问题。



现在的问题是如何做到最好。



目前的方法是将链接脚本(gnu ld)中的RAM地址替换为外部RAM的地址。



这种方法的问题是,在初始化期间,由于FSMC尚未初始化,芯片必须在内部RAM上运行。

似乎工作,但一旦pvPortMalloc运行,我们得到一个硬故障,这可能是由于取消引用伪造地址,我们可以看到变量在系统初始化时没有正确初始化(这是有道理的,我猜想,因为内部RAM根本没有使用,当它可能应该是)。



我意识到这是一个模糊的问题,但是在Cortex M4 MCU的外部RAM中运行代码时的一般方法是什么,更具体的STM32F4?



谢谢
FreeRTOSConfig.h 中的 configTOTAL_HEAP_SIZE 符号指定。 FreeRTOS使用它的 pvPortMalloc 函数在这个内存区域中分配任务堆栈,因此这里的主要目标是将FreeRTOS堆区放入外部SRAM。



FreeRTOS堆内存区域定义在 heap _ *。c 中(除 heap_3.c 使用标准库malloc并且没有定义任何自定义堆区),该变量称为 ucHeap 。您可以使用您的编译器扩展来设置其部分。对于GCC,这可能类似于:
$ b $ pre $ static uint8_t ucHeap [configTOTAL_HEAP_SIZE] __attribute__((section(.sram_data)) );

现在我们需要配置链接器脚本来将此自定义部分放置到外部SRAM中。有几种方法可以做到这一点,这取决于你使用的工具链。对于GCC来说,一种方法是为SRAM定义一个存储区域,然后为。sram_data添加一段以加入SRAM区域,如下所示: p>

 内存
{
...
/ *定义SRAM区域* /
sram:ORIGIN =< SRAM_START_ADDR>,LENGTH =< SRAM_SIZE>
}

部分
{
...
/ *定义.sram_data部分并将其放入sram区域* /
.sram_data :
{
*(。sram_data)
}> sram
...
}
$ b $ p

这会将 ucHeap 区域放置在外部SRAM中,而所有其他文本和数据区域将放置在默认的内存区域(内部闪存和RAM)。



几个注释:


  • 在启动任务之前,确保在调用任何FreeRTOS函数(如 xTaskCreate

  • 之前初始化SRAM控制器/ FSMC,所有堆栈分配的变量将被放置在 ucHeap (即ext RAM)中,但全局变量仍然分配在内部RAM中。如果仍有内部RAM大小问题,则可以使用编译器扩展将其他全局变量配置到。sram_section中(如ucHeap所示)

  • 如果您的代码使用动态内存分配,请确保使用 pvPortMalloc / vPortFree ,而不是stdlib malloc / free 。这是因为只有 pvPortMalloc / vPortFree 才会使用ext RAM中的ucHeap区域(并且它们是线程安全的,这是一个很好的选择)

  • 如果使用不同的内存块大小对 pvPortMalloc / vPortFree 执行大量动态任务创建/删除和内存分配,请考虑使用 heap_4 .c 而不是 heap_2.c 。当使用几个不同的块大小时, heap_2.c 存在内存碎片问题,而 heap_4.c 能够将相邻的空闲内存块放到一个大块中


    另一个(也可能更简单的)解决方案是将ucHeap变量定义为指针而不是数组,如下所示:

      static uint8_t * const ucHeap =< SRAM_START_ADDR>; 

    这不需要任何特殊的链接器脚本编辑,所有内容都可以放在默认的部分。请注意,通过此解决方案,链接程序不会明确地为堆保留任何内存,并且会丢失一些潜在有用的信息/错误(如堆区不适合ext RAM)。但只要你在外部RAM中只有 ucHeap ,并且你的 configTOTAL_HEAP_SIZE 小于外部RAM大小,很好。


    We have a thesis project at work were the guys are trying to get external RAM to work for the STM32F417 MCU. The project is trying out some stuff that is really resource hungry and the internal RAM just isn't enough.

    The question is how to best do this.

    The current approach has been to just replace the RAM address in the link script (gnu ld) with the address for external RAM.

    The problem with that approach is that during initialisation, the chip has to run on internal RAM since the FSMC has not been initialized.

    It seems to work but as soon as pvPortMalloc is run we get a hard fault and it is probably due to dereferencing bogus addresses, we can see that variables are not initialized correctly at system init (which makes sense I guess since the internal RAM is not used at all, when it probably should be).

    I realize that this is a vague question, but what is the general approach when running code in external RAM on a Cortex M4 MCU, more specifically the STM32F4?

    Thanks

    解决方案

    FreeRTOS defines and uses a single big memory area for stack and heap management; this is simply an array of bytes, the size of which is specified by the configTOTAL_HEAP_SIZE symbol in FreeRTOSConfig.h. FreeRTOS allocates tasks stack in this memory area using its pvPortMalloc function, therefore the main goal here is to place the FreeRTOS heap area into external SRAM.

    The FreeRTOS heap memory area is defined in heap_*.c (with the exception of heap_3.c that uses the standard library malloc and it doesn't define any custom heap area), the variable is called ucHeap. You can use your compiler extensions to set its section. For GCC, that would be something like:

    static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".sram_data")));
    

    Now we need to configure the linker script to place this custom section into external SRAM. There are several ways to do this and it depends again on the toolchain you're using. With GCC one way to do this would be to define a memory region for the SRAM and a section for ".sram_data" to append to the SRAM region, something like:

    MEMORY 
    {
        ...
        /* Define SRAM region */
        sram    : ORIGIN = <SRAM_START_ADDR>, LENGTH = <SRAM_SIZE>
    }
    
    SECTIONS 
    {
        ...
        /* Define .sram_data section and place it in sram region */
        .sram_data :
        {
            *(.sram_data)
        } >sram
        ...
    }
    

    This will place the ucHeap area in external SRAM, while all the other text and data sections will be placed in the default memory regions (internal flash and ram).

    A few notes:

    • make sure you initialize the SRAM controller/FSMC prior to calling any FreeRTOS function (like xTaskCreate)
    • once you start the tasks, all stack allocated variables will be placed in ucHeap (i.e. ext RAM), but global variables are still allocated in internal RAM. If you still have internal RAM size issues, you can configure other global variables to be placed in the ".sram_section" using compiler extensions (as shown for ucHeap)
    • if your code uses dynamic memory allocation, make sure you use pvPortMalloc/vPortFree, instead of the stdlib malloc/free. This is because only pvPortMalloc/vPortFree will use the ucHeap area in ext RAM (and they are thread-safe, which is a plus)
    • if you're doing a lot of dynamic task creation/deletion and memory allocation with pvPortMalloc/vPortFree with different memory block sizes, consider using heap_4.c instead of heap_2.c. heap_2.c has memory fragmentation problems when using several different block sizes, whereas heap_4.c is able to combine adjacent free memory blocks into a single large block

    Another (and possibly simpler) solution would be to define the ucHeap variable as a pointer instead of an array, like this:

    static uint8_t * const ucHeap = <SRAM_START_ADDR>;
    

    This wouldn't require any special linker script editing, everything can be placed in the default sections. Note that with this solution the linker won't explicitly reserve any memory for the heap and you will loose some potentially useful information/errors (like heap area not fitting in ext RAM). But as long as you only have ucHeap in external RAM and you have configTOTAL_HEAP_SIZE smaller than external RAM size, that might work just fine.

    这篇关于STM32F4在外部RAM中运行FreeRTOS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆