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.

msp432_startup_ccs_gcc.c in CCS 6.1.0.00104 is missing code to copy the data segment initializers from flash to SRAM

When CCS 6.1.0.00104 used used to create a project for a MSP432P401R device using the GCC v4.8.4 compiler, when main was reached global variables in the data segment had not been initialized. The msp432_startup_ccs_gcc.c file which was added by CCS at project creation contains the following resetISR function:

void resetISR(void)
{
    /* Copy the data segment initializers from flash to SRAM. */

    /* Zero fill the bss segment. */
    __asm("    ldr     r0, =__bss_start__\n"
          "    ldr     r1, =__bss_end__\n"
          "    mov     r2, #0\n"
          "    .thumb_func\n"
          "zero_loop:\n"
          "        cmp     r0, r1\n"
          "        it      lt\n"
          "        strlt   r2, [r0], #4\n"
          "        blt     zero_loop");
 
    /* Call the application's entry point. */
    main();
}

i.e. the code which should copy the the data segment initializers from flash to SRAM is missing.

Based upon startup_css_gcc.c for Tiva devices, the msp432_startup_ccs_gcc.c  needs the following to copy the data segment initializers from flash to SRAM:

//*****************************************************************************
//
// The following are constructs created by the linker, indicating where the
// the "data" and "bss" segments reside in memory.  The initializers for the
// for the "data" segment resides immediately following the "text" segment.
//
//*****************************************************************************
extern uint32_t __data_load__;
extern uint32_t __data_start__;
extern uint32_t __data_end__;
extern uint32_t __bss_start__;
extern uint32_t __bss_end__;

/* This is the code that gets called when the processor first starts execution */
/* following a reset event.  Only the absolutely necessary set is performed,   */
/* after which the application supplied entry() routine is called.  Any fancy  */
/* actions (such as making decisions based on the reset cause register, and    */
/* resetting the bits in that register) are left solely in the hands of the    */
/* application.                                                                */
void resetISR(void)
{
    uint32_t *pui32Src, *pui32Dest;

    //
    // Copy the data segment initializers from flash to SRAM.
    //
    pui32Src = &__data_load__;
    for(pui32Dest = &__data_start__; pui32Dest < &__data_end__; )
    {
        *pui32Dest++ = *pui32Src++;
    }

    /* Zero fill the bss segment. */
    __asm("    ldr     r0, =__bss_start__\n"
          "    ldr     r1, =__bss_end__\n"
          "    mov     r2, #0\n"
          "    .thumb_func\n"
          "zero_loop:\n"
          "        cmp     r0, r1\n"
          "        it      lt\n"
          "        strlt   r2, [r0], #4\n"
          "        blt     zero_loop");
 
    /* Call the application's entry point. */
    main();
}

  • Chester,

    Thank you for bringing this to our attention. We are investigating the issue and will get back to you shortly. Most likely, we will have to update the support package for this. I apologize for any trouble you have had.

    Regards,
    JH

    Update: This is now being tracked internally. Fixes for this bug will be included in a future support package update.

  • You still thinking about doing this in an update release?

    Cheers,
    Dana
  • An additional concern: copying the data initializers may take long enough that the MSP432 watchdog fires and resets the chip. So, a complete fix would disable the watchdog (probably with MAP_WDT_A_holdTimer()).

  • This snippet of msp432_startup_ccs_gcc.c is also broken:

    /* Interrupt vector table. Note that the proper constructs must be placed on this to */ /* ensure that it ends up at physical address 0x0000.0000 or at the start of */ /* the program if located at a start address other than 0. */ void (* const interruptVectors[])(void) __attribute__ ((section (".intvecs"))) = { (void (*)(void))((uint32_t)0x20004000), /* The initial stack pointer */ resetISR, /* The reset handler */

    The initial stack pointer is fixed regardless of data/bss use; I suspect the right answer is some linker magic with a stack segment. For the moment, I'm just changing it manually to 0x20010000 for the MSP432P401R; this is the same as the _STACK_END value used by the TI C toolchain.

  • To summarize the issues in msp432_startup_ccs_gcc.c:

    - data initializers need to be copied into SRAM
    - Watchdog needs to be held to avoid reset during data initializer copy (may unhold watchdog afterward)
    - Stack initialization is incorrect and likely places the stack in the middle of data (data corruption / faults)

    Where is the 'prototype' msp432_startup_ccs_gcc.c kept in CCS? I'd like to make the changes once so that any new project automatically gets them.
  • Dana,

    From what I have gathered, you can find the original msp432_startup_css_gcc.c (and non-gcc version) at the following path. The path assumes default installation.

    C:\TI\ccsv6\ccs_base\arm\include

    Regards,
    JH

  • Thank you! That is, in fact, where the startup source is located; now I'm less likely to forget to patch startup/gcc.

  • Hello,


    I wish to add some remarks:

    1/ The target value for new projects with GCC (TARGET_IS_FALCON) compiler is incorrect in file C:\ti\ccsv6\ccs_base\common\targetdb\devices\msp432p401r.xml line 68. I think it should be TARGET_IS_MSP432P4XX

    2/ When compiled with GCC, the example projet OutOfBox_MSP432P401R generate a fault at the first access to an FPU register (S15 in this case). I solve the problem by enabling the FPU with the instruction MAP_FPU_enableModule(); placed near the beginning of main function.


    I hope this can help.

  • Christian Schoffit said:

    2/ When compiled with GCC, the example projet OutOfBox_MSP432P401R generate a fault at the first access to an FPU register (S15 in this case). I solve the problem by enabling the FPU with the instruction MAP_FPU_enableModule(); placed near the beginning of main function.

    Oh yes, I ran into that also; I think I added that also to my MSP432 startup code for gcc. IIRC, if you have any FP in a function, gcc emits some context-saving code that faults if the FPU isn't turned-on.

    Dana

**Attention** This is a public forum