This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Linker zero_init Command

Hello,

While porting legacy code from an LPC2103 to a LPC1765 Cortex processor within the Keil environment I came accross the need to implement the linker zero_init attribute for a single byte variable as described by the following links:

(1) infocenter.arm.com/.../index.jsp
(2) http://www.keil.com/support/docs/3480.htm

The purpose of this variable was to be read on a system reset to determine whether the reset event was intentional or not and execute additional code if the reset event was intentional (ie: go into the ISP bootloader). As debugging shows, system reset causes RW variables to be zeroed when performing the BX from statup .asm code into application main().

However, when I implemented the change within a 'C' file as follows:

UINT8 Startup_Flags __attribute__( ( section( "NoInit"), zero_init) );

and linker scatter file as follows:

RW_IRAM1 0x10000000 UNINIT 0x00000100 { ;no init section
*(NoInit)
}

I was getting inconsistent results with the variable every time the reset event occurred, even though it was placed in the declared UNINIT memory region according to the memory map:

Startup_Flags 0x10000000 Data 1 main.o(NoInit)
SystemFrequency 0x10000100 Data 4 system_lpc17xx.o(.data)

As the region was declared to be a size of 256, I decided to add a dummy declaration along with the original to troubleshoot the issue further, as follows:

// Zero initialization section
UINT8 Startup_Flags __attribute__( ( section( "NoInit"), zero_init) );
UINT8 NoInitUnused[255] __attribute__( ( section( "NoInit"), zero_init) );

This initially showed promise until it too failed periodically (the variable Startup_Flags was located at 0x10000000 according to the memory map).

Startup_Flags 0x10000000 Data 1 main.o(NoInit)
NoInitUnused 0x100000ff Data 255 main.o(NoInit)

I then tried swapping the declarations in order to move the location of the variable to the LAST entry in the region (ie: 0x100000FF) as follows:

// Zero initialization section
UINT8 NoInitUnused[255] __attribute__( ( section( "NoInit"), zero_init) );
UINT8 Startup_Flags __attribute__( ( section( "NoInit"), zero_init) );

NoInitUnused 0x10000000 Data 255 main.o(NoInit)
Startup_Flags 0x100000ff Data 1 main.o(NoInit)

Now the results I am getting are consistently correct (so far) and I can invoke the ISP bootloader whenever the variable has the proper bit flag set.

The caveat seems to be that this zero_init command CAN be used and function properly, but under certain undocumented? conditions (ie: MUST have 8 declared bytes within the region and declaration order seems to be important). Has anyone else run into this issue? If so, how was it corrected? Or am I just misreading the documentation contained within the posted links? Thank you.