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.

MSP430G2755: Issue when moving/changing start address using linker command file

Part Number: MSP430G2755

Our project has a customer bootloader.

* The FLASH is partitioned to support both the bootloader and application.
  -- The bootloader starts at 0xE000. The bootloader and FLASH vectors are fixed
  -- The application starts at 0x8000

* A vector table is created in RAM and the FLASH vector table points to the RAM vector table.
  -- This way, the bootloader and application can overwrite the RAM vector table to suit each executable's requirements (ISR handlers).

* When the bootloader has finished loading or verifying the applicaiton it jumps to 0x8000 to run the application
  -- The linker command file for the application includes this to place the start of the application at 0x8000

     .boot > 0x8000
     {
       -l rts*.lib<boot_special.obj > (.text)
     }

* The issue I am having is that the application vector table is getting placed at address 0x8000.
  -- This means that the the jump to 0x8000 from the bootloader is now running an ISR vector which is not good.
  -- The expectation is to place the executable start of the application at 0x8000.
  -- Oddly, this is legacy code and is working in some older products. This may be an artifact of moving from "CCS7.x/16.9.2LTS" to "CCS11.2/21.6.0LTS."

* I find the documentation on the linker command file to be poor
  -- I have looked at the primer @:
     software-dl.ti.com/.../sdto_cgt_Linker-Command-File-Primer.html
  -- I also have SLAU132Y – "MSP430 Optimizing C/C++ Compiler v21.6.0.LTS"
  -- Here are some questions that is not covered in the documentation:
     # What is -l (shown above)?
     # The primer page shows an example using --library=Sinewave_lib.lib(.text).
       + When are double-dashes used?
       + Where is the list of double-dash syntax options (such as --libary)?
       + Where is the list of single-dash syntax options (such as -l)?
       + My example shows rts*.lib<boot_special.obj the primer shows Sinewave_lib.lib.
         % What are the requirements here?
         % Is the .lib format the same as a .obj?
       + Where is a list of parameters that can be installed in the <angle brackets>?
         % My example has boot_special.obj. Is this an intrinsic thing? How do I find the list of these things?
         % I found this about boot_special.obj. No help. What is this?
           $ e2e.ti.com/.../how-to-force-the-msp430-start-address-in-ccsv6

           $ Also from SLAA685, page 30 (this formatting seems different that the documentation)

             :: rts430x_lc_rd_eabi.lib : boot_special.obj
             :: (.text:_isr:_c_int00_noargs_noexit)
             :: : isr_trap.obj
             :: (.text:_isr:__TI_ISR_TRAP)

* Can you please provide a comprehensive list and explanation of all linker command file options, flags, syntax, abbreviations, etc.?


* So, how do I get the application start correctly at 0x8000?

  • The linker script for the application should tell the linker where to place .text sections. Your script fragment tells it where to put .boot segments. Not in a memory location but in some other named segment. Not sure if that works.

    An odd name for an application segment but not awful for the bootloader.

    My experience is with the GCC linker but from what I can see, the linker scripts are very similar if not identical. "info ld" is where I look first for information on that.

    To locate the application/boot loader I would alter the ROM size/location. The linker would then handle the job of locating .text (and other read only) sections there.

    With C code at least the beginning of the ROM image is not always, or even frequently the location where execution starts. Most often read only data for variable initializers and such goes here. You have to examine the contents of the reset vector (in its very own 2 byte section) to find that. Which makes writing a boot loader extra tricky.

  • I cannot find a way to attached a file to the forum which would be cleaner than pasting too much text into a post.

    I think TI used to allow attaching a file to the forum?

    Anyway, I guess I will need to paste the text here.

    Here is my linker command file.

    MEMORY
    {
    SFR : origin = 0x0000, length = 0x0010
    PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0
    PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100
    RAM_VECTORS : origin = 0x1100, length = 0x0080
    RAM : origin = 0x1180, length = 0x0F78
    INFOA : origin = 0x10C0, length = 0x0040
    INFOB : origin = 0x1080, length = 0x0040
    INFOC : origin = 0x1040, length = 0x0040
    INFOD : origin = 0x1000, length = 0x0040
    FLASH : origin = 0x8000, length = 0x5FE0
    FLASH_APPSWVER : origin = 0xDFE0, length = 0x0010
    FLASH_APPXSUM : origin = 0xDFF0, length = 0x0010
    FLASH_BOOTLOADER : origin = 0xE000, length = 0x1FE0
    FLASH_VECTORS : origin = 0xFFE0, length = 0x001E
    RESET : origin = 0xFFFE, length = 0x0002

    /*--------------------------------------------------------
    Forcing vectors, EXCEPT for RESET, to point to RAM
    addresses using FLASH_VECTORS & FLASHVECT_SEG. Not using
    default dynamic linking to functions. Original
    implementation saved here for reference.

    INT00 : origin = 0xFFE0, length = 0x0002
    INT01 : origin = 0xFFE2, length = 0x0002
    INT02 : origin = 0xFFE4, length = 0x0002
    INT03 : origin = 0xFFE6, length = 0x0002
    INT04 : origin = 0xFFE8, length = 0x0002
    INT05 : origin = 0xFFEA, length = 0x0002
    INT06 : origin = 0xFFEC, length = 0x0002
    INT07 : origin = 0xFFEE, length = 0x0002
    INT08 : origin = 0xFFF0, length = 0x0002
    INT09 : origin = 0xFFF2, length = 0x0002
    INT10 : origin = 0xFFF4, length = 0x0002
    INT11 : origin = 0xFFF6, length = 0x0002
    INT12 : origin = 0xFFF8, length = 0x0002
    INT13 : origin = 0xFFFA, length = 0x0002
    INT14 : origin = 0xFFFC, length = 0x0002
    ---------------------------------------------------------*/
    }

    /****************************************************************************/
    /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */
    /****************************************************************************/

    SECTIONS
    {
    .bss : {} > RAM /* GLOBAL & STATIC VARS */
    .data : {} > RAM /* GLOBAL & STATIC VARS */
    .sysmem : {} > RAM /* DYNAMIC MEMORY ALLOCATION AREA */
    .stack : {} > RAM (HIGH) /* SOFTWARE SYSTEM STACK */

    .boot > 0x8000
    {
    -l rts*.lib<boot_special.obj > (.text)
    }

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

    .pinit : {} /* C++ CONSTRUCTOR TABLES */
    .init_array : {} /* C++ CONSTRUCTOR TABLES */
    .mspabi.exidx : {} /* C++ CONSTRUCTOR TABLES */
    .mspabi.extab : {} /* C++ CONSTRUCTOR TABLES */
    } load = FLASH

    /*---[RUN FROM RAM]----------------------------------------*/
    RAMVECT_SEG : load = FLASH, run = RAM_VECTORS, table(_ramvector)
    .ovly : {} > FLASH

    /*---------------------------------------------------------*/
    .infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */
    .infoB : {} > INFOB
    .infoC : {} > INFOC
    .infoD : {} > INFOD

    .cio : {} > RAM /* C I/O BUFFER */
    .reset : {} > RESET
    FLASHVECT_SEG : {} > FLASH_VECTORS
    APPSWVER_SEG : {} > FLASH_APPSWVER

    /**** MSP430 INTERRUPT VECTORS ****/
    /*--------------------------------------------------------
    Forcing vectors, EXCEPT for RESET, to point to RAM
    addresses using FLASH_VECTORS & FLASHVECT_SEG. Not using
    default dynamic linking to functions. Original
    implementation saved here for reference.

    TIMER1_A1 : { * ( .int00 ) } > INT00 type = VECT_INIT
    TIMER1_A0 : { * ( .int01 ) } > INT01 type = VECT_INIT
    PORT1 : { * ( .int02 ) } > INT02 type = VECT_INIT
    PORT2 : { * ( .int03 ) } > INT03 type = VECT_INIT
    TRAPINT : { * ( .int04 ) } > INT04 type = VECT_INIT
    ADC10 : { * ( .int05 ) } > INT05 type = VECT_INIT
    USCIAB0TX : { * ( .int06 ) } > INT06 type = VECT_INIT
    USCIAB0RX : { * ( .int07 ) } > INT07 type = VECT_INIT
    TIMER0_A1 : { * ( .int08 ) } > INT08 type = VECT_INIT
    TIMER0_A0 : { * ( .int09 ) } > INT09 type = VECT_INIT
    WDT : { * ( .int10 ) } > INT10 type = VECT_INIT
    COMPARATORA : { * ( .int11 ) } > INT11 type = VECT_INIT
    TIMERB1 : { * ( .int12 ) } > INT12 type = VECT_INIT
    TIMERB0 : { * ( .int13 ) } > INT13 type = VECT_INIT
    NMI : { * ( .int14 ) } > INT14 type = VECT_INIT
    ---------------------------------------------------------*/
    }

    /****************************************************************************/
    /* INCLUDE PERIPHERALS MEMORY MAP */
    /****************************************************************************/

    -l msp430g2755.cmd

  • Use the "Insert" button and select "Code". This creates a scrollable window for long bits of code. Or linker scripts.

    Not that the complete script illuminated anything.

  • I noticed that there is a linker warning:

    <Linking>
    "../lnk_msp430g2755.cmd", line 108: warning #10068-D: no matching section
    warning #10229-D: output section ".data" refers to load symbol "$C$SL1" and hence cannot be compressed; compression "lzss" is ignored
    Finished building target: "abc.out"

    The line 108 is this line

    -l rts*.lib<boot_special.obj > (.text)

  • boot_special.com is located here:

    C:\ti\ccs1120\ccs\tools\compiler\ti-cgt-msp430_16.9.2.LTS\lib\src\boot_special.c

    It does not have a SECTION declaration in the C-file that I see. The C-file does have #pragma CLINK(xxxxx).

    I searched through "SLAU132Y – MSP430 Optimizing C/C++ Compiler v21.6.0.LTS"  and found no information about "CLINK". Really?!?!?

    So,  a few questions:

    * What the heck is #pragma CLINK?

       -- Where is it documented?

    * How do I force the "boot_special" to 0x8000 if there is no SECTION name of .boot?

       -- What is the proper syntax to accomplish this?

  • This doesn't solve your original problem, but maybe it provides a helpful clue. It looks like your referencing documentation for a different compiler version than what the boot_special.c file is based on. The path you listed shows that the file is part of the v16.9.2.LTS compiler, but you're referencing the user's guide for the v21.6.0.LTS compiler.  

    I also see that CLINK pragma is related to COFF object file format and this format has been deprecated from the latest MSP430 codgen tools. There is a note about that in the revision history of the MSP430 Compiler User's Guide you referenced: SLAU132Y

    You can read about the CLINK pragma in the older doc revision that corresponds to v16.9.2.LTS: SLAU132M

  • Thanks for the info on CLINK. I'll look at some older docs just for curiosity.

    As far as compilers (it's long read above), I mentioned that I moved from 16.9.2.LTS to 21.6.0LTS, And, yeah, I agree. I think it is related to that.

    I have been looking around and found that

    * compiler 21.6.0.LTS declares _c_int00..... in boot.c

    * compiler 16.9.2.LTS declares _c_int00..... in boot_special.c

    * See attached text file.....

    I search for the term "boot" in the .map file and got these results:

    26 9: FLASH_BOOTLOADER 0000e000 00001fe0 00000000 00001fe0 RWIX
    64 62: 00002030 00000002 rts430_eabi.lib : boot.c.obj (.stack)
    101 60: 00009604 00000040 main.obj (.text:BootDelay)
    136 62: 00009c0c 0000001c rts430_eabi.lib : boot.c.obj (.text:_c_int00_noargs)
    216 62: 0000fffe 00000002 rts430_eabi.lib : boot.c.obj (.reset)
    258 8: boot.c.obj 28 2 0
    Total found: 6

    I tried the various incarnations and still always get a "section not found" warning

    "../lnk_msp430g2755.cmd", line 108: warning #10068-D: no matching section
    rts*.lib<boot.obj> (.text:_c_int00_noargs)

    I hate to do it but I have to go back to the older compiler. I'm sure this can be done with the newer compiler but the linker command file syntax is elusive.

    MSP430 _c_int00 search results.txt
    C:\ti\ccs1120\ccs\tools\compiler\ti-cgt-msp430_16.9.2.LTS\lib\src\boot_special.c 9 KB C File 2/24/2017 5:22:47 PM 11/30/2023 11:21:19 AM 12/1/2023 5:02:09 PM 18
    56 #pragma CLINK(_c_int00_noargs)
    57 CSTART_DECL _c_int00_noargs()
    69 #pragma CLINK(_c_int00_noexit)
    70 CSTART_DECL _c_int00_noexit()
    83 #pragma CLINK(_c_int00_noinit_noargs_noexit)
    84 CSTART_DECL _c_int00_noinit_noargs_noexit()
    97 #pragma CLINK(_c_int00_noargs_noexit)
    98 CSTART_DECL _c_int00_noargs_noexit()
    110 #pragma CLINK(_c_int00_mpu)
    111 CSTART_DECL _c_int00_mpu()
    125 #pragma CLINK(_c_int00_noargs_mpu)
    126 CSTART_DECL _c_int00_noargs_mpu()
    141 #pragma CLINK(_c_int00_noexit_mpu)
    142 CSTART_DECL _c_int00_noexit_mpu()
    158 #pragma CLINK(_c_int00_noinit_noargs_noexit_mpu)
    159 CSTART_DECL _c_int00_noinit_noargs_noexit_mpu()
    175 #pragma CLINK(_c_int00_noargs_noexit_mpu)
    176 CSTART_DECL _c_int00_noargs_noexit_mpu()
    
    C:\ti\ccs1120\ccs\tools\compiler\ti-cgt-msp430_21.6.0.LTS\lib\src\boot.c 7 KB C File 5/27/2021 11:40:39 PM 8/7/2022 2:12:43 PM 12/1/2023 5:28:48 PM 16
    97 void _c_int00_template(int NEEDS_ARGS, int NEEDS_INIT, int NEEDS_MPU)
    130    _c_int00_template(1, 1, 0);
    133 CSTART_DECL _c_int00_noargs(void)
    135    _c_int00_template(0, 1, 0);
    138 CSTART_DECL _c_int00_noinit(void)
    140    _c_int00_template(1, 0, 0);
    143 CSTART_DECL _c_int00_noinit_noargs(void)
    145    _c_int00_template(0, 0, 0);
    148 CSTART_DECL _c_int00_mpu(void)
    150    _c_int00_template(1, 1, 1);
    153 CSTART_DECL _c_int00_noargs_mpu(void)
    155    _c_int00_template(0, 1, 1);
    158 CSTART_DECL _c_int00_noinit_mpu(void)
    160    _c_int00_template(1, 0, 1);
    163 CSTART_DECL _c_int00_noinit_noargs_mpu(void)
    165    _c_int00_template(0, 0, 1);
    
    

  • OK. I got it to work!!!

    Here's the linker command file entry:

    .boot > 0x8000
    {
        rts*.lib<boot.c.obj> (.text:_c_int00_noargs)
    }

    This also works

    .boot > 0x8000
    {
        -l rts*.lib<boot.c.obj> (.text:_c_int00_noargs)
    }

    So, in the older compiler, 16.9.2LTS this worked

    .boot > 0x8000
         {
           -l rts*.lib<boot_special.obj > (.text)
         }

    I tried several iterations to get this to work last Friday but was unsuccessful. This morning, I noticed one little detail that I had missed. I noticed this by searching the .map file.

    In the older compiler, 16.9.2LTS:

    boot_special.c compiled to boot_special.obj

    However, in the new compiler 21.6.0LTS

    boot.c compiles to boot.c.obj. 

    ---- NOT boot.obj (which is what I had used on the linker command file)

    Notice the ".c".obj !! The older compiler did NOT leave the ".c" extension in the .obj name

    See the excerpt from the .map file in my previous post above.

**Attention** This is a public forum