0

我正在尝试让 ARMCC 链接器将变量放入未初始化的 RAM 区域,但失败了(因为我需要它们在重置后仍然存在)。我在 scatter-link 文件中创建的区域指定UNINIT,并且在我的__attribute__调用中,我指定这是zero_initRAM(否则我知道 ARM 链接器认为它是DataRAM 并且不管你说什么都将它初始化为零) . 对于我下面的测试代码,.map文件显示链接器我的测试变量放入正确的区域:

Execution Region RW_IRAM1 (Base: 0x200032ac, Size: 0x00000004, Max: 0x00000400, ABSOLUTE, UNINIT)
Base Addr    Size         Type   Attr      Idx    E Section Name  Object
0x200032ac   0x00000004   Zero   RW         8    .bss.noinit      main.o

然而,有了这个测试代码:

#include "mbed.h"

// An unsigned int in an uninitialised RAM area
__attribute__ ((section(".bss.noinit"), zero_init))
unsigned int gRetained;

// Entry point
int main()
{
    printf("Retained RAM variable is %d.\n", gRetained);
    gRetained++;
    printf("Retained RAM variable incremented to %d.\n", gRetained);
    printf("Resetting...\n");
    wait_ms(1000);
    NVIC_SystemReset();
}

...我得到的输出是:

Retained RAM variable is 0.
Retained RAM variable incremented to 1.
Resetting...
Retained RAM variable is 0.
Retained RAM variable incremented to 1.
Resetting...
Retained RAM variable is 0.
...

谁能发现我做错了什么?

这是我的完整分散链接文件,RW_IRAM1我正在谈论的区域在哪里:

#! armcc -E

/* Default to no softdevice */
#if !defined(MBED_APP_START)
  #define MBED_APP_START 0x0
#endif

#if !defined(MBED_APP_SIZE)
  #define MBED_APP_SIZE 0x80000
#endif

/* Physical RAM */
#define MBED_RAM_PHYSICAL_START 0x20000000
#define MBED_RAM_PHYSICAL_SIZE 0x10000

/* Reserved areas */
#define MBED_RAM_SOFT_DEVICE_SIZE 0x31d0
#define MBED_RAM_UNINIT_AREA_SIZE 1024

/* If app_start is 0, do not set aside space for the softdevice */
#if MBED_APP_START == 0
  #define MBED_RAM_START  MBED_RAM_PHYSICAL_START
  #define MBED_RAM_SIZE   MBED_RAM_PHYSICAL_SIZE
#else
  #define MBED_RAM_START  (MBED_RAM_PHYSICAL_START + MBED_RAM_SOFT_DEVICE_SIZE)
  #define MBED_RAM_SIZE   (MBED_RAM_PHYSICAL_SIZE - MBED_RAM_SOFT_DEVICE_SIZE)
#endif

#define MBED_RAM0_START MBED_RAM_START
#define MBED_RAM0_SIZE  0xDC
#define MBED_RAM1_START (MBED_RAM0_START + MBED_RAM0_SIZE)
#define MBED_RAM1_SIZE  MBED_RAM_UNINIT_AREA_SIZE
#define MBED_RAM2_START (MBED_RAM1_START + MBED_RAM1_SIZE)
#define MBED_RAM2_SIZE  (MBED_RAM_SIZE - MBED_RAM0_SIZE - MBED_RAM1_SIZE)

LR_IROM1 MBED_APP_START MBED_APP_SIZE {
  ER_IROM1 MBED_APP_START MBED_APP_SIZE {
    *.o (RESET, +First)
    *(InRoot$$Sections) 
    .ANY (+RO)
  }

  RW_IRAM0 MBED_RAM0_START UNINIT MBED_RAM0_SIZE { ;no init section
    *(*nvictable)
  }
  RW_IRAM1 MBED_RAM1_START UNINIT MBED_RAM1_SIZE { ;no init section
    *(*noinit)
  }
  RW_IRAM2 MBED_RAM2_START MBED_RAM2_SIZE {
    .ANY (+RW +ZI)
  }
}

仅供参考,这是在具有 64 KB RAM 的 Nordic NRF52832 芯片上,我碰巧正在使用 mbed-os 构建,尽管我不认为这应该与问题有关。ARMCC 版本是 5.06 更新 6(内部版本 750)。

4

1 回答 1

0

嗯,ARM 工具支持已经确认我的链接器配置是正确的,并检查了我的 ELF 文件以确认没有任何东西会静态覆盖我的 noinit 区域。

问题似乎是在 NRF52832 上有一个 BLE 堆栈位于内存中,即使我从未激活 BLE,在 mbed-os 的某个地方,某些东西正在 MBED_RAM1_START 写入几 KB 的 BLE 配置数据,假设它拥有那个空间。所以解决方法是像 GCC 和 IAR 链接器文件一般做的那样,将 noinit 区域放在通常的 RAM 区域之后。问题是我不知道如何使用 ARM 工具来做到这一点,因为它们没有在链接器文件中单独识别堆区域。哼哼。

无论如何,要点是您在上面看到的配置确实有效,并且它是房间里的一头蓝色大象正在这个 RAM 上奔跑。

于 2018-10-03T10:33:42.013 回答