将部分拆分为多个内存区域

Posted

技术标签:

【中文标题】将部分拆分为多个内存区域【英文标题】:Split section into multiple memory regions 【发布时间】:2016-12-24 00:57:09 【问题描述】:

我正在 ARM Cortex-M 微控制器上开发一个应用程序,该微控制器具有两个 RAM 组 à 64kB。在内存映射中,第一个 bank 紧随其后的是第二个 bank。

内存库目前在我的链接描述文件中分为两个区域。第一个区域包含.bss.data 部分。第二个银行用于.heap.stack,每个只占用 1kB(我在 FreeRTOS 中使用不同的堆栈,它也管理自己的堆)。

我的问题是,.bss 对于第一家银行来说太大了。因此,我想将其中的一些内容转移到第二家银行。

实现此目的的一种方法是创建一个新部分,我们称之为.secondbss,它与第二个银行相关联。然后可以使用__attribute__((section(".secondbss"))) 将单个变量添加到此部分。

我不使用这个解决方案的原因是

我真的很想保持我的源代码的可移植性

可能有很多变量需要此属性,我不想为每个变量选择部分

有没有更好的解决方案?我已经将两个内存视为一个区域,但我不知道如何防止链接器在两个存储区之间的边界上错位数据。

如何在不使用__attribute__ 标志的情况下解决我的问题?

谢谢!

【问题讨论】:

【参考方案1】:

例如,您在 0x200000000x20010000 有 2 个银行。您想将 Bank2 用于堆和(主)堆栈。我假设您有很大的 .bss,因为 FreeRTOSConfig.h 中的 configTOTAL_HEAP_SIZE。现在在 FreeRTOS/Source/portable/MemMang/ 中查看堆源。 pvPortMalloc() 有 5 种实​​现内存分配。

查看您使用的 heap_X.c 中的行

/* Allocate the memory for the heap. */
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
    /* The application writer has already defined the array used for the RTOS
    heap - probably so it can be placed in a special segment or address. */
    extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
    static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */

因此您可以将configAPPLICATION_ALLOCATED_HEAP 设置为1,并告诉您链接器将ucHeap 设置为0x20010000

另一种方法是为每个设备编写标头,其中包括堆和堆栈地址以及编辑源。 对于 heap_1.c,我们可以进行下一步更改:

// somewhere in devconfig.h
#define HEAP_ADDR   0x20010000

// in heap_1.c
// remove code related ucHeap
//
// remove static uint8_t *pucAlignedHeap = NULL;
// and paste:
static uint8_t *pucAlignedHeap = (uint8_t *)HEAP_ADDR;

对于 heap_2.cheap_4.c 编辑函数 prvHeapInit() 也是如此。

注意heap_5.c,其中包含vPortDefineHeapRegions()

现在pvPortMalloc() 将返回指向 Bank2 中内存的指针。 pvPortMalloc() 用于分配任务堆栈、TCB 和用户变量。阅读来源。主堆栈的位置取决于您的设备/架构。对于 stm32 (ARM),请参见向量表或如何更改 MSP 寄存器。

【讨论】:

好的,谢谢。这已经很有帮助了。但是有没有办法告诉链接器将两个银行用于同一部分?尽管这应该可以解决我当前的问题,但我想知道如何使用这两家银行,就好像两者之间没有界限一样。在我看来,这应该只是对齐问题。 There 是与这些部分类似的问题。 “所以你可以手动放置特定的对象文件。” .bss2 (NOLOAD) : ALIGN(4) foo.o(.bss .bss.*) >RAM2 所有来自 foo.o.bss 数据将被放入 RAM2。请注意,您应该在启动时用零填充此内存,就像常规的 .bss 部分一样。

以上是关于将部分拆分为多个内存区域的主要内容,如果未能解决你的问题,请参考以下文章

从多个线程写入内存区域会导致争用吗?

java内存模型,内存区域

JVM内存分配及String常用方法

JVM的内存区域

JVM的内存区域

JVM的内存区域