eva*_*ing 1 ram gcc cortex-m3 stm32 ld
我们有一个论文项目正在工作,他们正试图让外部 RAM 为 STM32F417 MCU 工作。该项目正在尝试一些真正需要资源且内部 RAM 不够的东西。
问题是如何最好地做到这一点。
当前的方法只是将链接脚本 (gnu ld) 中的 RAM 地址替换为外部 RAM 的地址。
这种方法的问题在于,在初始化期间,由于 FSMC 尚未初始化,因此芯片必须在内部 RAM 上运行。
它似乎可以工作,但是一旦 pvPortMalloc 运行,我们就会遇到一个硬错误,这可能是由于取消引用虚假地址,我们可以看到变量在系统初始化时没有正确初始化(我猜这是有道理的,因为内部 RAM 不是完全使用,可能应该使用)。
我意识到这是一个模糊的问题,但是在 Cortex M4 MCU(更具体地说是 STM32F4)上的外部 RAM 中运行代码时,一般的方法是什么?
谢谢
小智 5
FreeRTOS 定义并使用单个大内存区域进行堆栈和堆管理;这只是一个字节数组,其大小由 中的configTOTAL_HEAP_SIZE符号指定FreeRTOSConfig.h。FreeRTOS 使用其pvPortMalloc函数在此内存区域中分配任务堆栈,因此此处的主要目标是将 FreeRTOS 堆区域放入外部 SRAM。
FreeRTOS 堆内存区域定义在heap_*.c(heap_3.c使用标准库 malloc的除外,它没有定义任何自定义堆区域),该变量称为ucHeap。您可以使用编译器扩展来设置其部分。对于 GCC,这将类似于:
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ((section (".sram_data")));
Run Code Online (Sandbox Code Playgroud)
现在我们需要配置链接描述文件以将此自定义部分放入外部 SRAM。有几种方法可以做到这一点,这又取决于您使用的工具链。使用 GCC 做到这一点的一种方法是为 SRAM 定义一个内存区域和一个用于".sram_data"附加到 SRAM 区域的部分,例如:
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
...
}
Run Code Online (Sandbox Code Playgroud)
这会将区域放置ucHeap在外部 SRAM 中,而所有其他文本和数据部分将放置在默认存储区域(内部闪存和 ram)中。
一些注意事项:
xTaskCreate)之前初始化 SRAM 控制器/FSMCucHeap(即ext RAM)中,但全局变量仍然分配在内部RAM 中。如果您仍然有内部 RAM 大小问题,您可以配置其他全局变量以放置在".sram_section"using 编译器扩展中(如 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>;
Run Code Online (Sandbox Code Playgroud)
这不需要任何特殊的链接器脚本编辑,所有内容都可以放在默认部分中。请注意,使用此解决方案,链接器不会为堆显式保留任何内存,并且您将丢失一些潜在有用的信息/错误(例如堆区域不适合 ext RAM)。但是只要您只有ucHeap外部 RAM 并且您的 RAMconfigTOTAL_HEAP_SIZE小于外部 RAM 大小,这可能会正常工作。