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.

msp430 GCC startup source code

Other Parts Discussed in Thread: MSP430FR5969, MSP430F249

I'm using GCC and trying to figure out a way to solve USCI28 issue. For that I wanted to create a custom startup code that would allow me to optimize startup and add the things I need. Where/how can I get the source for for the current startup used by GCC?

  • Gennadiy Kiryukhin said:

    I'm using GCC and trying to figure out a way to solve USCI28 issue. For that I wanted to create a custom startup code that would allow me to optimize startup and add the things I need. Where/how can I get the source for for the current startup used by GCC?

    I just tried to find it but we've switched over to the msp432 and there things are in different places.

    try compiling with the -v (verbose) switch.  That should tell you every file that it is processing, including start up files.

  • It is written in assembly and probably named crt0 or something like that.
  • On the MSP430, gcc's run-time library is not implemented by GNU libc but by newlib; the startup code is in libgloss/msp430/crt0.S.

  • The startup code in in crt.o object file in msp430-gcc-4.1.0.0_win32\msp430-gcc-5.3.0.219_win32\msp430-elf\lib\430 which is pre-compiled.

    In order to modify it you have to download the full GCC source tarball to get the source assembly-language file. See here: software-dl.ti.com/.../index_FDS.html

    Once you have that, I believe (but don't hold me to it) that the relevant source file is msp430-gcc-4.1.0.0_source-full\msp430-gcc-5.3.0.219_source-full\newlib\libgloss\msp430\crt0.S

    I am unable to tell you how to build that, as I don't use GCC myself and haven't tried to figure out.

    Starting point anyway.
  • Hi!


    You can add your own code to the startup without modifying the supplied startup code.

    See how I add a function to the startup code in my post https://e2e.ti.com/support/development_tools/code_composer_studio/f/81/p/534236/1946470#1946470.

    Copy the stackInit(void) function and rename it. Don't forget to copy all __attribute__ lines as well.

    To place it just after the stack has been initialized use the section ".crt_0001workaroundUSCI28" instead.

    Use the code referenced by just to know where you want to place your code by using the correct section attribute.

  • The workaround must be executed before the stack pointer register is initialized. This is not possible with any .crt_xxxx section.
  • Clemens Ladisch said:
    The workaround must be executed before the stack pointer register is initialized. This is not possible with any .crt_xxxx section.

    Sure no problem, as said just use the correct section name.

    Eg. this code:

    void workaroundUSCI28(void) __attribute__ ((naked));
    void workaroundUSCI28(void) __attribute__ ((used));
    void workaroundUSCI28(void) __attribute__ ((section (".crt_0000_before_start")));
    void workaroundUSCI28(void)
    {
    	/*
    	 * Only use as few variables as possible and only of type register.
    	 * You've certainly got no stack set up.
    	 */
    	register uint8_t somevar;
    
        /* code */
    	__no_operation();
    }
    

    will be placed before stack init, see this snippet from the map file created:

    .text           0x0000450c      0x314
                    0x0000450c                PROVIDE (_start, .)
                    0x0000450c                . = ALIGN (0x2)
    *(SORT(.crt_*))
     .crt_0000_before_start
                    0x0000450c        0x2 ./main.o
                    0x0000450c                workaroundUSCI28
     .crt_0000start
                    0x0000450e        0x4 /home/USER/ti/msp430_gcc-4.1.0.0/bin/../lib/gcc/msp430-elf/5.3.0/../../../../msp430-elf/lib/large/crt0.o
                    0x0000450e                __crt0_start
     .crt_0100init_bss
                    0x00004512       0x10 /home/USER/ti/msp430_gcc-4.1.0.0/bin/../lib/gcc/msp430-elf/5.3.0/../../../../msp430-elf/lib/large/libcrt.a(crt_bss.o)
                    0x00004512                __crt0_init_bss
     .crt_0300movedata
                    0x00004522       0x14 /home/USER/ti/msp430_gcc-4.1.0.0/bin/../lib/gcc/msp430-elf/5.3.0/../../../../msp430-elf/lib/large/libcrt.a(crt_movedata.o)
                    0x00004522                __crt0_movedata
     .crt_0700call_init_then_main
    

  • And what are the contents of the reset vector? Still __crt0_start?
  • Clemens Ladisch said:
    And what are the contents of the reset vector? Still __crt0_start?



    Yes it still is, good point indeed. But I've figured out how to fix this as well.

    In your project create a new file called "mycrt0.S" with the following contents:

        .section ".resetvec-patched", "a"
    __msp430_resetvec_hook:
        .word    workaroundUSCI28
    

    In the linker script, eg. for my project msp430fr5969.ld, change the following lines

      __reset_vector :
      {
        KEEP (*(__interrupt_vector_56))
        KEEP (*(__interrupt_vector_reset))
        KEEP (*(.resetvec))
      } > RESETVEC
    

    to

      __reset_vector :
      {
        KEEP (*(.resetvec-patched))
      } > RESETVEC
    

    Look up the location of the reset vector in the linker script, here for example I'm using msp430fr5969.ld:

    MEMORY {
    [...]
      RESETVEC         : ORIGIN = 0xFFFE, LENGTH = 0x0002
    }
    

    Now recompile and start a debug session.

    Open a disassembly view and enter the address of the reset vector, in this example 0xfffe, to resolve where reset jumps to (click image for full size):



    In this example the start of the code is at 0x4420, the encircled number in the picture.

    Now enter that address into the disassembly view and you should get this (click image for full size):


    The NOP represents code you'd want to run before everything else.

    If you want to debug the whole startup deselect the following two settings in the debug settings(click image for full size):

  • Example worked out:

    Implementing the work-around requires two pieces: inserting the work-around code before crt0_start (loading the stack pointer SP) and changing the reset vector to point to the work-around crt0_beforestart code so it executes on reset, catching the spurious USCI28 reset vectors.

    1. Create a new file usci28.c (name is not critical):

    /*
     * usci28.c
     *
     * Work around USCI28 errata.
     *
     * This MUST go before crt_0000start which resets the stack pointer,
     * destroying our ability to return from the interrupt (misvectored to
     * the reset vector).
     *
     * "beforestart" sorts before "start", which achieves our objective.
     */
     
    void __crt0_beforestart(void) __attribute__ ((naked));
    void __crt0_beforestart(void) __attribute__ ((used));
    void __crt0_beforestart(void) __attribute__ ((section (".crt_0000beforestart")));
    void __crt0_beforestart(void)
    {
        __asm("\t BIT.B\t #0x0C,&0x0001");  // If USB0 TXIE or RXIE is set, an erroneous reset occurred
        __asm("\t JZ\t Start_Normal");      //
        __asm("\t RETI");                   // so return from the interrupt call.
        __asm("Start_Normal:");
    }
     
    void __crt0_resetvec(void) __attribute__ ((naked));
    void __crt0_resetvec(void) __attribute__ ((used));
    void __crt0_resetvec(void) __attribute__ ((section (".resetvec_usci28")));
    void __crt0_resetvec(void)
    {
        __asm("\t .word __crt0_beforestart");
    }

    1. Edit your linker control file, e.g. msp430f249.ld, to change .resetvec to resetvec_usci28:

    @@ -117,7 +117,7 @@ SECTIONS
       {
         KEEP (*(__interrupt_vector_32))
         KEEP (*(__interrupt_vector_reset))
    -    KEEP (*(.resetvec))
    +    KEEP (*(.resetvec_usci28))
       } > RESETVEC

       .rodata :

  • Gerald Van Baren said:
        __asm("\t BIT.B\t #0x0C,&0x0001");  // If USB0 TXIE or RXIE is set, an erroneous reset occurred

    Being picky, I think the comment should say "UCB0" or "USCI_B0" rather than "USB0".

  • In our case we check configuration of one of the ports to know if we entered the reset erroneously. Who know what kind of other interrupt could cause a reset. This method is implementation specific and may need to be tweaked if used in a different project that keeps that particular port in default (reset) configuration.

**Attention** This is a public forum