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.

Boot loading and Watchdog initialization

My text section had a lot of code in the beginning that I didn't know what it was since the main was way later. I realised that this function is added in the beginning of text but called from text:_isr.

void AUTO_INIT_HOLD_WDT(void)
{
    run_binit();

    uint16_t initial_WDT = WDTCTL;
    WDTCTL = HOLD_WDT;

    run_cinit();

    WDTCTL = RESTORE_WDT(initial_WDT);

    run_pinit();
}

(1) Why is it on text and not in text:_isr ? Apart from that,  (2) why is the watchdog enabled by default ?

The previous function is called from this one:

#pragma CLINK(_c_int00_noargs_noexit)
CSTART_DECL _c_int00_noargs_noexit()
{
   STACK_INIT();
   if (_system_pre_init() != 0) _auto_init(); 
   main(0);
   abort();
}

_auto_init() calls _auto_init_hold_wdt somehow even though the names are different. It turns out that the function _system_pre_init() always returns 1, the code is (copy/pasted from pre_init.c). (3) Does anyone know why ?

int _system_pre_init(void)
{
    return 1;
}

I also noticed that all the code is not compiled.

As you can see, the code line run_binit() is not in there, it directly jumps to uint16_t initial_WDT = WDTCTL. (4) Does anyone know why ? I have optimization off.

Last questions are about binit, ciit and pinit. I already read this page and says something like it copies valus from a table in order to initialize variables. (5) Is that correct ? I quote the important part here:

3.3.3.1 BINIT

The BINIT (boot-time initialization) copy table is special in that the target will automatically perform the copying at auto-initialization time. Refer to Section 8.8.4.2 for more about the BINIT copy table name. The BINIT copy table is copied before .cinit processing.

3.3.3.2 CINIT

EABI .cinit tables are special kinds of copy tables. Refer to Section 3.3.2.1 for more about using the .cinit section with the ROM model and Section 3.3.2.2 for more using it with the RAM model.

I didn't find anything about pinit(), (6) any ideas ?. I checked in my program and these are my values for my __TI_Handler_Table_Base : 00B0 0001 4442 0000 2400 0000. If put it in a table:

Load    Run
00B0    0001   
4442    0000   
2400    0000

I can't understand it. It doesn't make sense for me. (7) A brief description of binit, ciit and pinit would help me a lot.

That's all. I know it's a long post but I think the questions are clear and if you know the answers even if it's only a couple of lines could help me out, so please answer to the ones you know by writing what question you are answering to, just like I did though all the post.

Everything is appreciated. Thank you very much.

  • First, a bit of background.  The compiler tools, and the linker in particular, take many factors into account in order to make the startup code as small as possible.  I have not learned all the details of this process.  I just know it works well.  

    Jon Zarate said:
    (1) Why is it on text and not in text:_isr ?

    So the linker command file can do things like this ...

        .text:_isr        : {}  > FRAM          /* Code ISRs                         */
    #ifndef __LARGE_DATA_MODEL__
        .text             : {} >> FRAM          /* Code                              */
    #else
        .text             : {} >> FRAM2 | FRAM  /* Code                              */
    #endif

    This allocates the .text:_isr section into FRAM.  When __LARGE_DATA_MODEL__ is in effect, the rest of the code goes in FRAM2 first, then FRAM.  This respects some  HW limitation on MSP430.  The ISR vectors, or the address they branch to, or something like that, has to be in the first 16-bits of the address range.

    Jon Zarate said:
    (2) why is the watchdog enabled by default ?

    Probably because you link with --cinit_hold_wdt=off.  

    Jon Zarate said:
    _auto_init() calls _auto_init_hold_wdt somehow even though the names are different.

    The linker maps the symbols.  All references to _auto_init are changed to refer to _auto_init_hold_wdt instead.  You can do general symbol mapping with the --symbol_map linker option.

    Jon Zarate said:
    It turns out that the function _system_pre_init() always returns 1, the code is (copy/pasted from pre_init.c). (3) Does anyone know why ?

    Please search for the _system_pre_init function in the compiler manual.

    Jon Zarate said:
    the code line run_binit() is not in there, it directly jumps to uint16_t initial_WDT = WDTCTL. (4) Does anyone know why ?

    You probably don't have any boot-time initialization tables, so this code is not needed.  I don't know the mechanics of how the linker makes this particular change.

    Jon Zarate said:
    A brief description of binit, ciit and pinit would help me a lot.

    The .binit section holds the boot-time initialization copy tables.  Such tables are created by lines like this in the linker command file ...

        .bcode: load = ROM, run= RAM, table(BINIT)
    

    This feature is not commonly used in MSP430 linker command files.  A general discussion of copy tables is in this application note.  The BINIT tables get a brief mention.  Overall, you can probably ignore BINIT handling.

    The .cinit section holds tables used to initialize global variables.  These tables are processed by the boot routine.  

    The .pinit section holds the addresses of C++ constructors that need to be called before main runs.  If you don't use C++, then you can ignore these tables.

    Thanks and regards,

    -George