AR# 30878


13.1 EDK - My Software Application Operates Improperly after a CPU Reset


When a CPU reset takes place, the application code begins to run from the reset vector location. The .data sections in an application contain initialized variables that are modifiable. Each time an application runs, it modifies the .data section variables as described in the application code. If an application relies on the .data initial values, it causes unpredictable results from the application each time the processor is reset.


This problem can manifest itself in a number of ways, but one example is that malloc might return a NULL pointer after a reset. This happens because malloc relies on variables inside the .data section to operate properly.

To solve this issue, you need to store a copy of the .data section in memory that is later used to re-initialize the .data section when the CPU is reset. This copy can be located anywhere in memory as long as it is not modified.

Method 1
Non-volatile memory is a good location to store the copy because it ensures that the copy is not accidentally changed. The steps below are written specifically for the PowerPC processor and assume the .data and .data1 sections are contiguous.
  1. Create a 'CopyData' function placed in 'copydata.c' to copy data sections from flash to their final destination, see (Xilinx XAPP642).

    void copydata(void) {    int *src_rom = (int *)XPAR_FLASH_MEM0_BASEADDR; // pointer src_rom gets the base address of flash     int *dst_ram = &__data_start; // pointer dst_ram gets the value(address) of .data section    int *end_ram = &__data1_end; // pointer end_ram gets the ending address of .data1 section     while (dst_ram < end_ram) { // copy the data from ROM to RAM      *dst_ram++ = *src_rom++;     }     return;  } /* end of copy.c */  
  2. Copy $EDK/sw/lib/ppc405/src/xil-crt0.s to your project directory.
  3. Add bl copydata right before bl main in the xil-crt0.s file:

    /* Call __init */  bl __init  /* copy data section */  bl copydata  /* Let her rip */  bl main  
  4. Compile xil-crt0.s and copydata.c in an EDK Shell:
    EDK_Shell> powerpc-eabi-gcc -c copydata.c -c xil-crt0.s
  5. Add the -B./<path_to_copydata.o_and_xil-crt0.o_files>/ extra compile switch for your software application.
  6. Compile your software application.
  7. Extract the data sections to binary format from your software application's ELF:
    powerpc-eabi-objcopy -O binary -j .data -j .data1 executable.elf flash.bin
  8. Use flashwriter to write the flash.bin into the flash device starting at the base address.
    Now, when you press the CPU reset, the CopyData function executes and copies the data sections from flash into RAM.

Method 2

Method 1 is an option if the final design has access to flash, but if the application is intended to run from block ram and does not need flash this second method may be a better approach. This second method uses a custom linker script with the copy data routine inside main(). The custom linker script adds a .datacopy section that is the same size as the data section. The copy of the data section resides in RAM. The following shows the normal .data section along with the custom .datacopy section:
.data : {  . = ALIGN(4);  __data_start = .;  *(.data)  *(.data.*)  *(.gnu.linkonce.d.*)  __data_end = .; } > ilmb_cntlr_dlmb_cntlr   /* create a section */ .datacopy : {  . = ALIGN(4);  __datacopy = .;  . += SIZEOF(.data); } > ilmb_cntlr_dlmb_cntlr 

Next is the 'C' code that demonstrates the copying of sections from one location to another using the variables that have been previously defined in the linker script:
#include "xparameters.h" #include "stdio.h" #include "xutil.h" //====================================================   volatile int i = 0xDEADBEEF; extern unsigned char __datacopy; extern unsigned char __data_start; extern unsigned char __data_end;   int main (void) {   unsigned char *dataCopyStart = &__datacopy;   unsigned char *dataStart = &__data_start;   unsigned char *dataEnd = &__data_end;     if (i == 0xDEADBEEF)     while(dataStart < dataEnd)       *dataCopyStart++ = *dataStart++;         else     while(dataStart < dataEnd)       *dataStart++ = *dataCopyStart++;    print("-- Entering main() --\r\n");   i = 0;     print("-- Exiting main() --\r\n");     return 0; } 

Linked Answer Records

Master Answer Records

Answer Number Answer Title Version Found Version Resolved
AR# 30878
Date 04/15/2013
Status Active
Type General Article
Tools More Less
People Also Viewed