This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Data initialization issue



I am trying to convert a TIABI project for TMS470 WEGA to EABI. I had a working project for TIABI. It seems to work for the most part, except the part with initialized globals.

I used init script that was in the "TMS470 ARM ABI Migration" file, but it doesn't work. I'm guessing I have issues with the linker file. Can anyone help me with this?

When I run the init part up until main function, uninitialized variables are set to 0, which is correct, but initialized variables are not initialized. Instead, they have 0xFFFFFFFF value. 

I'm using TMS470 v4.6.4.

My linker file:

/****************************************************************************************/
/* OPTIONS */
/****************************************************************************************/
-c /* LINK USING C CONVENTIONS */
-a
-stack 0x1000 /* SOFTWARE STACK SIZE */
-heap 0x2000 /* HEAP AREA SIZE */


/****************************************************************************************/
/* SPECIFY THE SYSTEM MEMORY MAP */
/****************************************************************************************/
MEMORY
{
VECTORS (X) : origin=0x0000000 length=0x20 
ROM (RX) : origin=0x0000030 length=0x00009000
STACKS (RW) : origin=0x08002000 length=0x00002000
RAM (RW) : origin=0x08004000 length=0x00005000
APIRAM (RW) : origin=0x01800000 length=0x01000

/* peripherals */
HETPROG (RW) : origin=0x00900000 length=0x800 
EXTCAN (RW) : origin=0x00190000 length=0x600
DPRAM_ETH(RW) : origin=0x00200000 length=0xFFFF 
ADC (RW) : origin=0xfff7f000 length=0x100
API (RW) : origin=0xfff7c400 length=0x400
SCCRAM0 (RW) : origin=0xfff7dc00 length=0x400
SCC0 (RW) : origin=0xfff7e000 length=0x400
HCCRAM0 (RW) : origin=0xfff7e400 length=0x400
HCC0 (RW) : origin=0xfff7e800 length=0x400
GIO0 (RW) : origin=0xfff7ec00 length=0x400
/* A2D0 (RW) : origin=0xfff7f000 length=0x400*/
SCI0 (RW) : origin=0xfff7f400 length=0x400
SPI0 (RW) : origin=0xfff7f800 length=0x400
HET0 (RW) : origin=0xfff7fc00 length=0x400

/* sar module addresses */
MMC (RW) : origin=0xFFFFFD00 length=0x40
DEC (RW) : origin=0xFFFFFE00 length=0x60
SYS (RW) : origin=0xFFFFFFD0 length=0x30
CMRTI (RW) : origin=0xFFFFFF00 length=0xcf /* Clock module & Real Time Interrupt */

/****************************************************************************************/


/****************************************************************************************/
/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */
/****************************************************************************************/
SECTIONS
{
.intvecs : {} > VECTORS /* INTERRUPT VECTORS */
.startup : {} > 0x00000030 /* START ADDRESS */
.stack : {
_StackUSER_ = .+ (0x1000 - (4+128+4+4+512));
_StackFIQ_ = _StackUSER_ + 4;
_StackIRQ_ = _StackFIQ_ + 128;
_StackABORT_ = _StackIRQ_ + 4;
_StackUND_ = _StackABORT_ + 4;
_StackSUPER_ = _StackUND_ + 512;
} > STACKS /* SOFTWARE SYSTEM STACK */

.bss : {} > RAM /* GLOBAL & STATIC VARS */
.sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */

.text : {} > ROM /* CODE */
.cinit : {} > ROM /* INITIALIZATION TABLES */
.const : {} > ROM /* CONSTANT DATA */

.ADC : {_e_ADC1 = .;} > ADC
.APIRAM : {_e_APIRAM = .;} > APIRAM
.API : {_e_SARAPI_ST = .;} > API
.SPI0 : {_e_SPI0_ST = .;} > SPI0 
.SCI0 : {_e_SCI0_ST = .;} > SCI0 
.GIO0 : {_e_GIO_ST = .;} > GIO0
.HET0 : {_e_HET0_ST = .;} > HET0 
/* .A2D0 : {_e_A2D0_ST = .;} > A2D0*/ 
.SCC0 : {_e_CAN0_ST = .;} > SCC0 
.HCC0 : {_e_CAN1_ST = .;} > HCC0 
.HETCODE : { _e_HETPROGRAM0_UN = .;} > HETPROG /* HET PROGRAM */

.MMC : {_e_SARMMC_ST = .;} > MMC
.DEC : {_e_SARDEC_ST = .;} > DEC
.SYS : {_e_SARSYS_ST = .;} > SYS
.CIM : {_e_SARCIM_ST = .+0x20;} > CMRTI 
.CMRTI : {_e_SARRTI_ST = .;} > CMRTI
.EXTCAN : {_g_CanController = .;} > EXTCAN
/*
.EXTCAN : {_g_CanController2_st = .+0x100;} > EXTCAN 
.EXTCAN : {_g_CanController3_st = .+0x200;} > EXTCAN
.EXTCAN : {_g_CanController4_st = .+0x300;} > EXTCAN 
.EXTCAN : {_g_CanController5_st = .+0x400;} > EXTCAN
.EXTCAN : {_g_CanController6_st = .+0x500;} > EXTCAN 
*/
.DPRAM_ETH : {} > DPRAM_ETH 
}

&"&"&"
-o %2

My init script:

/*----------------------------------------------------------------------------*/
#include "lld_types.h"

#include "TMS470Wega.h"
/*----------------------------------------------------------------------------*/

void auto_initialize();

typedef void (*handler_fptr)(const unsigned char *in,
unsigned char *out);
#define HANDLER_TABLE __TI_Handler_Table_Base
#pragma WEAK(HANDLER_TABLE)
extern unsigned int HANDLER_TABLE;
extern unsigned char *__TI_CINIT_Base;
extern unsigned char *__TI_CINIT_Limit;
extern unsigned int __TI_Handler_Table_Limit;

/*----------------------------------------------------------------------------*/
/* system registers */

// lots of code which I cut out

/*----------------------------------------------------------------------------*/
/* Startup Routine */

void c_int00()

{
/* start pll lock */
SYSTEM->CSDISCLR = 0x02;

/* stacks */
asm(" ldr sp,[pc]"); /* svc stack */
asm(" mov pc,pc");
asm(" .word 0x08001100");

asm(" mov r0,#0xD1"); /* fiq stack */
asm(" msr cpsr,r0");
asm(" ldr sp,[pc]");
asm(" mov pc,pc");
asm(" .word 0x08001200");

asm(" mov r0,#0xD2"); /* irq stack */
asm(" msr cpsr,r0");
asm(" ldr sp,[pc]");
asm(" mov pc,pc");
asm(" .word 0x08001300");

asm(" mov r0,#0xDF"); /* user/system stack */
asm(" msr cpsr,r0");
asm(" ldr sp,[pc]");
asm(" mov pc,pc");
asm(" .word 0x08001000");

/* Initialize VIM table */

{
unsigned i;

for (i = 0; i < 96; i++)
{
VIM_RAM->ISR[i] = s_vim_init[i];
}
}

/* initalise the C global variables */
auto_initialize();

/* power-up peripharals */
PCR->PSPWRDWNCLR0 = 0xFFFFFFFF;
PCR->PSPWRDWNCLR1 = 0xFFFFFFFF;
PCR->PSPWRDWNCLR2 = 0xFFFFFFFF;
PCR->PSPWRDWNCLR3 = 0xFFFFFFFF;

/* enable peripharals */
SYSTEM->CLKCNTL = 0x01010100;

/* set IRQ/FIQ priorities */
VIM->FIRQPR0 = 0x00000000;
VIM->FIRQPR1 = 0x00000000;
VIM->FIRQPR2 = 0x00000000;

/* enable interrupts */
VIM->REQMASKSET0 = 0x00000fff;
VIM->REQMASKSET1 = 0x00000000;
VIM->REQMASKSET2 = 0x00000000;


PCR->PCSPWRDWNSET0 = 0xFFFFFFFF;
PCR->PCSPWRDWNSET1 = 0xFFFFFFFF;
SYSTEM->SYSPC1 = 0x00000001;
SYSTEM->SYSPC2 = 0x00000001;

/* call the application */
main();
exit();
}

/*----------------------------------------------------------------------------*/

void auto_initialize()
{
unsigned char **table_ptr;
unsigned char **table_limit;
/*--------------------------------------------------------------*/
/* Check if Handler table has entries. */
/*--------------------------------------------------------------*/
if (&__TI_Handler_Table_Base >= &__TI_Handler_Table_Limit)
return;
/*---------------------------------------------------------------*/
/* Get the Start and End of the CINIT Table. */
/*---------------------------------------------------------------*/
table_ptr = (unsigned char **)&__TI_CINIT_Base;
table_limit = (unsigned char **)&__TI_CINIT_Limit;
while (table_ptr < table_limit)
{
/*-------------------------------------------------------------*/
/* 1. Get the Load and Run address. */
/* 2. Read the 8-bit index from the load address. */
/* 3. Get the hander function pointer using the index from */
/* handler table. */
/*-------------------------------------------------------------*/
unsigned char *load_addr = *table_ptr++;
unsigned char *run_addr = *table_ptr++;
unsigned char handler_idx = *load_addr++;
handler_fptr handler =
(handler_fptr)(&HANDLER_TABLE)[handler_idx];
/*-------------------------------------------------------------*/
/* 4. Call the handler and pass the pointer to the load data */
/* after index and the run address. */
/*-------------------------------------------------------------*/
(*handler)((const unsigned char *)load_addr, run_addr);
}
}

  • I cannot reproduce this problem.  I would need a complete, compilable test case that reproduces the problem, including the main function, the complete command-line options, and the header files that the initialization code includes.

    When you say "initialized variables [..] have 0xFFFFFFFF value," do you mean all initialized variables, or just some of them?

    Notice you are explicitly setting some memory values to 0xFFFFFFFF in the initialization routine after autoinit has been called. Is this the origin of the values you are seeing in your initialized variables?

  • Thank you very much for your response!!

    I attached the files for a simplified project. Do you need anything else?

    All of the initialised globals have the same problem. You can see the example in the main file. 

    Command line options are visible here:

    Compiling ...
    intvecs.s ... with parameters "X:\TI\tms470_4_6_4\bin\cl470.exe -c D:\example\intvecs.s -g -mv4 --abi=eabi"
    main.c ... with parameters "X:\TI\tms470_4_6_4\bin\cl470.exe -g -mv4 --abi=eabi D:\example\main.c"
    startupPTB5BAPGF.c ... with parameters "X:\TI\tms470_4_6_4\bin\cl470.exe -g -mv4 --abi=eabi D:\example\startupPTB5BAPGF.c"
    Linking ... with parameters "X:\TI\tms470_4_6_4\bin\lnk470.exe --unused_section_elimination=off D:\example\link32.XCL -mv4 --abi=eabi -lX:\TI\TMS470_4_6_4\lib\libc.a"
    "Sample.out (Dir:D:\example\Debug\)" ... was successfully generated.

    ProjectFiles.zip
  • The likely problem is that you need to define _c_int00 as _c_int00 in the C file in EABI mode, otherwise you get the _c_int00 from the RTS library instead.  Remember, EABI doesn't add leading underscores.

    However, I can't really test this because I don't have ARM hardware, and the simulator really doesn't like the inline assembly to initialize the various stacks, for some reason.

  • I am a bit confused. The way I understood it, if I used c_int00, it's supposed to be in eabi mode (instead of _c_int00). I tried both ways just to be sure, though, but the same happens both ways. I checked and I always get my code linked in. Since I have my own implementation of c_int00 I tried also with the default one (linked only if I used _c_int00), but it worked just the same. 

    I think this isn't the problem, because before, when I was trying to compile mixed eabi and tiabi objects, I was getting a linker error related to this, which I'm not getting now.

    I changed the files a bit to get around the inlined code, if this helps. I included the changed files in the attached archive. 

    Should I have linked the .data section somewhere else except default? Do you maybe have a working eabi example which I could dissect? I was looking for it online with no luck. 

    added start.s:

    .state32
    .global c_int00
    .global start
    start:
    ldr sp,[pc]; /* svc stack */
    mov pc,pc;
    .word 0x08001100;

    mov r0,#0xD1; /* fiq stack */
    msr cpsr,r0;
    ldr sp,[pc];
    mov pc,pc;
    .word 0x08001200;

    mov r0,#0xD2; /* irq stack */
    msr cpsr,r0;
    ldr sp,[pc];
    mov pc,pc;
    .word 0x08001300;

    mov r0,#0xDF; /* user/system stack */
    msr cpsr,r0;
    ldr sp,[pc];
    mov pc,pc;
    .word 0x08001000;

    b c_int00

    modified intvec.s:

    .state32

    .global start

    .sect ".intvecs"

    b start ; RESET INTERRUPT
    b #-8 ; UNDEFINED INSTRUCTION INTERRUPT
    b #-8 ; SOFTWARE INTERRUPT
    b #-8 ; ABORT (PREFETCH) INTERRUPT
    b #-8 ; ABORT (DATA) INTERRUPT
    b #-8 ; RESERVED
    ldr pc,[pc,#-0x1B0] ; IRQ INTERRUPT
    b #-8 ; FIQ INTERRUPT

    .end

    ProjectFiles2.zip
  • I have a rather different idea to propose.  The auto_initialize routine from TMS470EABIMigration.pdf is not what is normally used.  The routine tested with the compiler is in auto_init.asm, which can be found in compiler install root directory\lib\rtssrc.zip.  Another detail ... It is named __TI_auto_init and not auto_initialize.  This assembly routine could be different in a way that is subtle, yet significant.  Perhaps you should try using it, or adapting from it, or something like that.

    Thanks and regards,

    -George

  • I linked in this function, but no luck.

    I stepped the init function and it looks like it reads the cinit table (repeats once), but then it loads the c_pinit and c_pinit_end values, which are both 0. I'm guessing this is why nothing gets initialized.

    _b1_loop_ is executed once, _loop_ is not executed even once. Tables that were generated during the compile are:

    LINKER GENERATED COPY TABLES

    __TI_cinit_table @ 00000a04 records: 1, size/record: 8, table size: 8
    .data: load addr=00000868, load size=00000192 bytes, run addr=000006c4, run size=000001a0 bytes, compression=rle


    LINKER GENERATED HANDLER TABLE

    __TI_handler_table @ 000009fc records: 2, size/record: 4, table size: 8
    index: 0, handler: __TI_decompress_rle
    index: 1, handler: __TI_decompress_none

    So if I understand the init function correctly, it is OK, that _b1_loop_ is executed only once, but the second one should loop through the vars? I tried adding .init_array section to the linker file, but nothing changed.

  • I don't recognize the symbols c_pinit and c_pinit_end, but the .pinit section is the name for the COFF ABI C++ global variable initialization data; it should be empty in EABI.  Instead in EABI the section .init_array is used.  It too should be empty if you don't have any C++ global variables.

  • They are used in the script that George Mock suggested. It is used for eabi initialization - the way I understood it it has nothing to do with .pinit section. I am a bit confused as to which value should be there. I don't have access to that script at this moment, so I will paste the relevant part first thing tomorrow. Thanks for your help so far!

  • I'm attaching the script. As you can see, c_pinit has value of SHT$$INIT_ARRAY$$Base. I'm not sure what this is supposed to mean. If I have .data and .bss section and and let's say 4 vars in each, how many times should each loop be executed? If I know this, I'll probably be able to figure out the rest.

    Relevant parts are as follows:

    /* ... */

    .if __TI_EABI_ASSEMBLER
    ;*------------------------------------------------------
    ;* If eabi, process the compressed cinit table. The format
    ;* is as follows:
    ;* |4-byte load addr|4-byte run addr|
    ;* |4-byte load addr|4-byte run addr|
    ;*
    ;* Processing steps:
    ;* 1. Read load and run address.
    ;* 2. Read one byte at load address, say idx.
    ;* 3. Get pointer to handler at handler_start[idx]
    ;* 4. call handler(load_addr + 1, run_addr)
    ;*------------------------------------------------------
    _b1_:
    LDR r5, c_cinit_start
    LDR r7, c_cinit_end
    LDR r6, handler_start
    _b1_loop_:
    CMP r5,r7
    BCS _b1_loop_end_
    LDMIA r5!, {r0,r1}
    LDRB r4, [r0]
    LSL r4, r4, #2
    LDR r4, [r6,r4]
    ADD r0, r0, #1
    .if __TI_TMS470_V7M3__
    BLX r4
    .else
    BL IND$CALL
    .endif
    B _b1_loop_
    _b1_loop_end_:
    .else
    ;*------------------------------------------------------
    ;* PERFORM AUTO-INITIALIZATION. IF CINIT IS -1, THEN
    ;* THERE IS NONE.
    ;*------------------------------------------------------
    _b1_: LDR r0, c_cinit
    MOV r7, #1
    CMN r0, r7
    BEQ _c1_
    BL perform_cinit
    .endif

    _c1_: LDR r5, c_pinit
    .if (!__TI_EABI_ASSEMBLER)
    ;*------------------------------------------------------
    ;* IN NON-EABI MODE, THERE IS NO INITIALIZATION ROUTINE
    ;* IF PINIT IS -1. ALSO, PINT IS NULL TERMINATED. ITERATE
    ;* OVER THE PINIT TABLE AND CALL THE INITIALIZATION ROUTINE
    ;* FOR CONSTRUCTORS.
    ;* NOTE THAT r7 IS PRESERVED ACROSS AUTO-INITIALIZATION.
    ;*------------------------------------------------------
    CMN r5, r7
    BEQ _c3_
    B _c2_
    _loop_:
    .if __TI_TMS470_V7M3__
    BLX r4
    .else
    BL IND$CALL
    .endif
    _c2_: LDMIA r5!, {r4}
    CMP r4, #0
    BNE _loop_
    _c3_:
    .else
    ;*------------------------------------------------------
    ;* IN EABI MODE, INIT_ARRAY IS NOT NULL TERMINATED. START
    ;* FROM THE INIT_ARRAY START (C_PINIT) AND ITERATE TILL
    ;* INIT_ARRAY END (C_PINT_END)
    ;*------------------------------------------------------
    LDR r7, c_pinit_end
    _loop_:
    CMP r5, r7
    BCS _loop_end_ ; If r5 is GE r7, we have reached the end.
    LDMIA r5!, {r4}
    .if __TI_TMS470_V7M3__
    BLX r4
    .else
    BL IND$CALL
    .endif
    B _loop_
    _loop_end_:
    .endif

    /* ... */

    ;***************************************************************
    ;* CONSTANTS USED BY THIS MODULE
    ;***************************************************************
    c_binit .long binit

    .if __TI_EABI_ASSEMBLER
    c_pinit .long SHT$$INIT_ARRAY$$Base
    c_pinit_end .long SHT$$INIT_ARRAY$$Limit
    c_cinit_start .long __TI_CINIT_Base
    c_cinit_end .long __TI_CINIT_Limit
    handler_start .long __TI_Handler_Table_Base
    .else
    c_pinit .long pinit
    c_cinit .long cinit
    .endif


    ;******************************************************
    ;* UNDEFINED REFERENCES *
    ;******************************************************
    .global binit
    .global cinit
    .global COPY_IN_RTN

    .if .TMS470_16BIS
    .global IND$CALL
    .else
    .global IND_CALL
    .endif

    .if __TI_EABI_ASSEMBLER
    .weak SHT$$INIT_ARRAY$$Base
    .weak SHT$$INIT_ARRAY$$Limit
    .weak __TI_CINIT_Base
    .weak __TI_CINIT_Limit
    .weak __TI_Handler_Table_Base
    .else
    .global pinit
    .endif

    .end

    auto_init.asm
  • OK, I solved the problem. I compared the project to some gcc project I had and noticed the special syntax in the linker file. Adding this solved the issue:

    .data : {} > RAM AT > ROM

  • That does not appear to be correct syntax for the linker command file.  Is this copy-n-paste directly from the file?

    -George

  • Yes. This is the relevant part from the linker file:


    .intvecs : {} > VECTORS /* INTERRUPT VECTORS */
    .startup : {} > 0x00000030 /* START ADDRESS */
    .stack : {
    _StackUSER_ = .+ (0x1000 - (4+128+4+4+512));
    _StackFIQ_ = _StackUSER_ + 4;
    _StackIRQ_ = _StackFIQ_ + 128;
    _StackABORT_ = _StackIRQ_ + 4;
    _StackUND_ = _StackABORT_ + 4;
    _StackSUPER_ = _StackUND_ + 512;
    } > STACKS /* SOFTWARE SYSTEM STACK */

    .bss : {} > RAM /* GLOBAL & STATIC VARS */
    .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */

    .text : {} > ROM /* CODE */
    .cinit : {} > ROM /* INITIALIZATION TABLES */
    .const : {} > ROM /* CONSTANT DATA */
    .data : {} > RAM AT > ROM /* DATA */