ARMCC linker: creating a non-initialised region

876 views Asked by At

I'm trying, and failing, to get the ARMCC linker to put variables into an area of RAM which is NOT initialised (because I need them to survive across a reset). The region I have created in the scatter-link file specifies UNINIT and, in my __attribute__ call, I am specifying that this is zero_init RAM (otherwise I'm aware that the ARM linker thinks it is Data RAM and zero-initialises it no matter what you say). For my test code below the .map file shows that the linker is putting my test variable into the correct region:

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

Yet with this test code:

#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();
}

...the output I get is:

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.
...

Can anyone spot what I'm doing wrong?

Here is my scatter-link file in full where RW_IRAM1 is the region I'm talking about:

#! 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)
  }
}

FYI, this is on a Nordic NRF52832 chip with 64 kbytes RAM and I happen to be building with mbed-os, though I don't believe this should have a bearing on the problem. ARMCC version is 5.06 update 6 (build 750).

1

There are 1 answers

0
Rob On

Well, ARM tools support have confirmed that my linker configuration is correct and have checked my ELF file to confirm that nothing is statically overwriting my noinit zone.

The problem seems to be that on the NRF52832 there is a BLE stack sitting in memory and that, even though I never activate BLE, something, somewhere in mbed-os, is writing a few kbytes of BLE configuration data at MBED_RAM1_START, assuming it owns that space. So the fix is to do as GCC and IAR linker files generally do and place the noinit region after the usual RAM area. Trouble is I don't know how to do that with ARM tools as they don't identify the heap area separately in the linker file. Ho hum.

Anyway, the main point is that the configuration you see above does actually work and that it is a blue elephant in the room that is tromping on this RAM.