Uninitialized Variables with LPCXpresso

Believe it or not but every static variable in C is initialized whether you explicitly set a value or not. If you don’t set a variable then the variable will be initialized to 0. Almost all of the time that behaviour is exactly what you need.

I was working on a watchdog timer module this week and I ran into a problem. When I design a watchdog module, I make sure that every major task and/or function is working properly before resetting the watchdog timer. If the module detects an error then I like to save the error into RAM so that it is available for debugging later after the CPU resets. This has saved a ton of time over the years.

Since C initializes all static variables, you have to declare the variable in a different linker section. I choose the name “.noinit” because it’s already present in the MSP430 GNU compilers and I’m familiar with it. Here’s an example of a variable described this way for GNU C:

volatile int32 __attribute__ ((section(".noinit"))) variable;

Using the volatile keyword keeps the optimizer from deleting the variable from your code which may or may not happen depending on how you use it. The int32 type is a signed 32 bit integer (one day I’ll have to post a header file that automatically assigned all of these types, regardless of the compiler). The attribute part of the declaration puts “variable” into memory section “.noinit”.

If you use LPCXpresso, you need to tell it about the noinit memory section. Otherwise your code will debug fine but you won’t be able to program standalone .AXF files as I found out the hard way. So the first thing you need to do is make sure you compile your code at least once so that the standard linker files are automatically generated. Then follow these instructions to disable regenerating the automatic linker files. You can then copy the scripts (*.ld) from the Debug directory and copy them to a new directory called “linkscripts” at the same level as your source directory “src”. Rename all the files so the the “Debug” part of the filename is gone.

Now you have to edit the main script file, named .ld. You need to change the include directory path and add the noinit section like below:

/*
 * GENERATED FILE - DO NOT EDIT
 * 
 * (C) Code Red Technologies Ltd, 2008-9
 * Generated C linker script file for LPC1113/301
 * (created from nxp_lpc11_c.ld (v3.5.6 (201011041518)) on Fri Nov 26 10:10:24 PST 2010)
 */

/* Make sure you edit these paths to include ../linkscripts! */
INCLUDE "../linkscripts/project_lib.ld"
INCLUDE "../linkscripts/project_mem.ld"
ENTRY(ResetISR)
SECTIONS
{
    .text :
    {
        KEEP(*(.isr_vector))
        *(.text*)
        *(.rodata*)
    } > MFlash24
    
    /* for exception handling/unwind - some Newlib functions (in common with C++ and STDC++) use this. */
    .ARM.extab :
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > MFlash24
    
    __exidx_start = .;
    .ARM.exidx :
    {
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > MFlash24>    
    __exidx_end = .;
    
    _etext = .;
    
    .data :
    {
        _data = .;
        *(vtable)
        *(.data*)
        _edata = .;
    } > RamLoc8 AT>MFlash24
    
    /* zero initialized data */
    .bss :
    {
        _bss = .;
        *(.bss*)
        *(COMMON)
        _ebss = .;
    } > RamLoc8
    
    /* Add no init section! */
    /* non initialized variables */
    .noinit (NOLOAD) :
    {
        *(.noinit)
    } > RamLoc8
    
    /* Where we put the heap with cr_clib */
    .cr_heap :
    {
        end = .;
        _pvHeapStart = .;
    } > RamLoc8
    
    _vRamTop = __top_RamLoc8 ;
    _vStackTop = _vRamTop - 0;
}

Then rebuild your project and you’re done!