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.

Parents
  • 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().
    

    Putting the ZI variable into a UNINIT section means that the variable will not be zeroed (or changed) by the image's startup code. You should see the same value at the "BX from startup" as in main().

    But Startup_Flags could be being changed by other things, for example powering off and on the RAMs, other code, if any, running before the image or other code in the image before Startup_Flags is read.

Reply
  • 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().
    

    Putting the ZI variable into a UNINIT section means that the variable will not be zeroed (or changed) by the image's startup code. You should see the same value at the "BX from startup" as in main().

    But Startup_Flags could be being changed by other things, for example powering off and on the RAMs, other code, if any, running before the image or other code in the image before Startup_Flags is read.

Children