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.

Linking section at start of memory address!

Other Parts Discussed in Thread: MSP430F5529

Hi there,

 Can I link specific section at the start of FLASH code memory?

Thanks in advance!

With best regards,

Rahul

  • Hi Rahul,

    Are you wanting to store some code at a particular location in FLASH memory (in this case, at the low end of the Flash)? You might want to look into using the CODE_SECTION() pragma - you can find more information in the compiler guide www.ti.com/lit/pdf/slau132

    If it's constant data you want to store rather than code, I think you can use the DATA_SECTION() pragma instead.

    There's also some more information in other threads on this forum, like this one, if you start searching for these pragma names: http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/19229/74778.aspx#74778

    Regards,

    Katie

  • Hi,

    using TI CGT/Compiler v4.3.1 in CCS v6.0, i can do the following (using target MSP430F5529 as example):

    - source test code:

    #include <msp430.h> 
    
    #pragma RETAIN(var1)
    #pragma DATA_SECTION(var1, ".var1")
    const unsigned char var1 = 0xAA;
    
    #pragma RETAIN(var2)
    #pragma DATA_SECTION(var2, ".var2")
    const unsigned int var2 = 0x1234;
    
    #pragma RETAIN(var3)
    #pragma DATA_SECTION(var3, ".var3")
    const unsigned long int var3 = 0x00C0FFEE;
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    	
    	return 0;
    }
    

    - linker command file (see how ".var1", ".var2", ".var3" are defined:

    SECTIONS
    {
        .bss        : {} > RAM                /* GLOBAL & STATIC VARS              */
        .data       : {} > RAM                /* GLOBAL & STATIC VARS              */
        .sysmem     : {} > RAM                /* DYNAMIC MEMORY ALLOCATION AREA    */
        .stack      : {} > RAM (HIGH)         /* SOFTWARE SYSTEM STACK             */
    
        .text       : {}>> FLASH2 | FLASH     /* CODE                              */
        .text:_isr  : {} > FLASH              /* ISR CODE SPACE                    */
        .cinit      : {} > FLASH | FLASH2     /* INITIALIZATION TABLES             */
        .const      : {} > FLASH | FLASH2     /* CONSTANT DATA                     */
        .cio        : {} > RAM                /* C I/O BUFFER                      */
    
    	.var1       : {} > 0xF000
    	.var2       : {} > 0xF100
    	.var3       : {} > 0xF200
    
        .pinit      : {} > FLASH              /* C++ CONSTRUCTOR TABLES            */
        .init_array : {} > FLASH              /* C++ CONSTRUCTOR TABLES            */
        .mspabi.exidx : {} > FLASH            /* C++ CONSTRUCTOR TABLES            */
        .mspabi.extab : {} > FLASH            /* C++ CONSTRUCTOR TABLES            */
    
        .infoA     : {} > INFOA              /* MSP430 INFO FLASH MEMORY SEGMENTS */
        .infoB     : {} > INFOB
        .infoC     : {} > INFOC
        .infoD     : {} > INFOD
    
        /* MSP430 INTERRUPT VECTORS          */
        .int00       : {}               > INT00
        .int01       : {}               > INT01
        .int02       : {}               > INT02
        .int03       : {}               > INT03
        .int04       : {}               > INT04
        .int05       : {}               > INT05
        .int06       : {}               > INT06
        .int07       : {}               > INT07
        .int08       : {}               > INT08
        .int09       : {}               > INT09
        .int10       : {}               > INT10
        .int11       : {}               > INT11
        .int12       : {}               > INT12
        .int13       : {}               > INT13
        .int14       : {}               > INT14
        .int15       : {}               > INT15
        .int16       : {}               > INT16
        .int17       : {}               > INT17
        .int18       : {}               > INT18
        .int19       : {}               > INT19
        .int20       : {}               > INT20
        .int21       : {}               > INT21
        .int22       : {}               > INT22
        .int23       : {}               > INT23
        .int24       : {}               > INT24
        .int25       : {}               > INT25
        .int26       : {}               > INT26
        .int27       : {}               > INT27
        .int28       : {}               > INT28
        .int29       : {}               > INT29
        .int30       : {}               > INT30
        .int31       : {}               > INT31
        .int32       : {}               > INT32
        .int33       : {}               > INT33
        .int34       : {}               > INT34
        .int35       : {}               > INT35
        .int36       : {}               > INT36
        .int37       : {}               > INT37
        .int38       : {}               > INT38
        .int39       : {}               > INT39
        .int40       : {}               > INT40
        RTC          : { * ( .int41 ) } > INT41 type = VECT_INIT
        PORT2        : { * ( .int42 ) } > INT42 type = VECT_INIT
        TIMER2_A1    : { * ( .int43 ) } > INT43 type = VECT_INIT
        TIMER2_A0    : { * ( .int44 ) } > INT44 type = VECT_INIT
        USCI_B1      : { * ( .int45 ) } > INT45 type = VECT_INIT
        USCI_A1      : { * ( .int46 ) } > INT46 type = VECT_INIT
        PORT1        : { * ( .int47 ) } > INT47 type = VECT_INIT
        TIMER1_A1    : { * ( .int48 ) } > INT48 type = VECT_INIT
        TIMER1_A0    : { * ( .int49 ) } > INT49 type = VECT_INIT
        DMA          : { * ( .int50 ) } > INT50 type = VECT_INIT
        USB_UBM      : { * ( .int51 ) } > INT51 type = VECT_INIT
        TIMER0_A1    : { * ( .int52 ) } > INT52 type = VECT_INIT
        TIMER0_A0    : { * ( .int53 ) } > INT53 type = VECT_INIT
        ADC12        : { * ( .int54 ) } > INT54 type = VECT_INIT
        USCI_B0      : { * ( .int55 ) } > INT55 type = VECT_INIT
        USCI_A0      : { * ( .int56 ) } > INT56 type = VECT_INIT
        WDT          : { * ( .int57 ) } > INT57 type = VECT_INIT
        TIMER0_B1    : { * ( .int58 ) } > INT58 type = VECT_INIT
        TIMER0_B0    : { * ( .int59 ) } > INT59 type = VECT_INIT
        COMP_B       : { * ( .int60 ) } > INT60 type = VECT_INIT
        UNMI         : { * ( .int61 ) } > INT61 type = VECT_INIT
        SYSNMI       : { * ( .int62 ) } > INT62 type = VECT_INIT
        .reset       : {}               > RESET  /* MSP430 RESET VECTOR         */ 
    }
    
    /****************************************************************************/
    /* INCLUDE PERIPHERALS MEMORY MAP                                           */
    /****************************************************************************/
    
    -l msp430f5529.cmd
    

    - result TI-TXT file:

    @4400
    31 40 00 44 B1 13 94 00 0C 93 02 24 B1 13 00 00 
    0C 43 B1 13 84 00 B1 13 98 00 
    @f000
    AA 
    @f100
    34 12 
    @f200
    EE FF C0 00 
    @ffd2
    8E 00 8E 00 8E 00 8E 00 8E 00 8E 00 8E 00 8E 00 
    8E 00 8E 00 8E 00 8E 00 8E 00 8E 00 8E 00 8E 00 
    8E 00 8E 00 8E 00 8E 00 8E 00 8E 00 00 44 3A 14 
    19 42 5C 01 B2 40 80 5A 5C 01 3F 40 00 00 3F 90 
    01 00 23 28 3F 40 00 00 3F 90 01 00 1E 28 3A 40 
    00 00 3A 80 00 00 3A 50 07 00 5A 09 38 40 00 00 
    3C 48 3D 48 3E 48 3F 48 C7 0C CB 0D 1C 53 0D 63 
    0F 18 4B 5B 00 18 4B D7 6B 4B 4B 4B 5B 06 00 18 
    5B 4B 00 00 4B 13 1A 83 EB 23 79 C2 39 D0 08 5A 
    82 49 5C 01 3F 40 00 00 3F 90 00 00 08 24 3A 40 
    00 00 02 3C 6A 13 2A 52 3A 90 00 00 FB 23 37 16 
    10 01 B2 40 80 5A 5C 01 0C 43 10 01 32 D0 10 00 
    FD 3F 1C 43 10 01 03 43 FF 3F 
    q
    

    - result MAP file:

    SECTION ALLOCATION MAP
    
     output                                  attributes/
    section   page    origin      length       input sections
    --------  ----  ----------  ----------   ----------------
    ......................
    
    .var1      0    0000f000    00000001     
                      0000f000    00000001     main.obj (.var1:var1)
    
    .var2      0    0000f100    00000002     
                      0000f100    00000002     main.obj (.var2:var2)
    
    .var3      0    0000f200    00000004     
                      0000f200    00000004     main.obj (.var3:var3)
    
    ......................
    

  • If you for example want bootup-code at a specific  location:
    use rseg cstart and edit the compiler added linker-file in your project folder

    //segment         Usage
    //CSTART         Program startup code

    // Code
    -Z(CODE)CSTART,ISR_CODE,CODE_ID=C000-FFDF

  • Rahul,

    You didn't specify which toolchain you are using. The answers Katie and Leo provided are for CCS. The answer is different if you are using IAR or mspgcc.

  • Hi Leo, Katie And Brian,

    I using CCS v5.5. And Let me rephrase my question here.

    Lets say I have 100 functions in my application.

    Here is my abstract .cmd file.

    Linker command file 

    MEMORY

    {

    //---------------

     FLASH                   : origin = 0x8000, length = 0x4000

    //---------------

    }

    SECTIONS

    {

    //--------------

      .text: :{} > FLASH

    //---------------

    }

    Linker will link all .text sections randomly in FLASH memory area. I mean, Functions 10 might linked at 0x8000 and 2 at 0xA000 And so on.

    So, My Question is, can I link specific section at the start of flash?. I don't want to use CODE_SECTION because I don't know the length of that section.

    Thanks in advance,

    Rahul

  • Rahul,

    ok got it. I just tried this example with CCS v5.5, Compiler version v4.2.4:

    - example code:

    #include <msp430.h> 
    
    
    void fn1(void)
    {
      P1DIR |= BIT0;
    }
    
    unsigned int fn2(unsigned int in)
    {
      return(in+1);
    }
    
    void fn3(void)
    {
      P1OUT ^= BIT0;
    }
    
    void main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
      fn1();
      fn2(2);
      fn3();
    
      while(1);
    }
    

    as you can see there are three functions in the example: fn1(), fn2(), fn3()

    - modifying the linker command file (take attention to the ".text" sections):

    SECTIONS
    {
        .bss        : {} > RAM                /* GLOBAL & STATIC VARS              */
        .data       : {} > RAM                /* GLOBAL & STATIC VARS              */
        .sysmem     : {} > RAM                /* DYNAMIC MEMORY ALLOCATION AREA    */
        .stack      : {} > RAM (HIGH)         /* SOFTWARE SYSTEM STACK             */
    
        .text       : {}>> FLASH2 | FLASH     /* CODE                              */
        .text:fn1   : {} > 0x6000
        .text:fn2   : {} > 0x8000
        .text:fn3   : {} > 0xA000
        .text:_isr  : {} > FLASH              /* ISR CODE SPACE                    */
        .cinit      : {} > FLASH | FLASH2     /* INITIALIZATION TABLES             */
        .const      : {} > FLASH | FLASH2     /* CONSTANT DATA                     */
        .cio        : {} > RAM                /* C I/O BUFFER                      */
    
        .pinit      : {} > FLASH              /* C++ CONSTRUCTOR TABLES            */
        .init_array : {} > FLASH              /* C++ CONSTRUCTOR TABLES            */
        .mspabi.exidx : {} > FLASH            /* C++ CONSTRUCTOR TABLES            */
        .mspabi.extab : {} > FLASH            /* C++ CONSTRUCTOR TABLES            */
    
        .infoA     : {} > INFOA              /* MSP430 INFO FLASH MEMORY SEGMENTS */
        .infoB     : {} > INFOB
        .infoC     : {} > INFOC
        .infoD     : {} > INFOD
    
        /* MSP430 INTERRUPT VECTORS          */
        .int00       : {}               > INT00
        .int01       : {}               > INT01
        .int02       : {}               > INT02
        .int03       : {}               > INT03
        .int04       : {}               > INT04
        .int05       : {}               > INT05
        .int06       : {}               > INT06
        .int07       : {}               > INT07
        .int08       : {}               > INT08
        .int09       : {}               > INT09
        .int10       : {}               > INT10
        .int11       : {}               > INT11
        .int12       : {}               > INT12
        .int13       : {}               > INT13
        .int14       : {}               > INT14
        .int15       : {}               > INT15
        .int16       : {}               > INT16
        .int17       : {}               > INT17
        .int18       : {}               > INT18
        .int19       : {}               > INT19
        .int20       : {}               > INT20
        .int21       : {}               > INT21
        .int22       : {}               > INT22
        .int23       : {}               > INT23
        .int24       : {}               > INT24
        .int25       : {}               > INT25
        .int26       : {}               > INT26
        .int27       : {}               > INT27
        .int28       : {}               > INT28
        .int29       : {}               > INT29
        .int30       : {}               > INT30
        .int31       : {}               > INT31
        .int32       : {}               > INT32
        .int33       : {}               > INT33
        .int34       : {}               > INT34
        .int35       : {}               > INT35
        .int36       : {}               > INT36
        .int37       : {}               > INT37
        .int38       : {}               > INT38
        .int39       : {}               > INT39
        .int40       : {}               > INT40
        RTC          : { * ( .int41 ) } > INT41 type = VECT_INIT
        PORT2        : { * ( .int42 ) } > INT42 type = VECT_INIT
        TIMER2_A1    : { * ( .int43 ) } > INT43 type = VECT_INIT
        TIMER2_A0    : { * ( .int44 ) } > INT44 type = VECT_INIT
        USCI_B1      : { * ( .int45 ) } > INT45 type = VECT_INIT
        USCI_A1      : { * ( .int46 ) } > INT46 type = VECT_INIT
        PORT1        : { * ( .int47 ) } > INT47 type = VECT_INIT
        TIMER1_A1    : { * ( .int48 ) } > INT48 type = VECT_INIT
        TIMER1_A0    : { * ( .int49 ) } > INT49 type = VECT_INIT
        DMA          : { * ( .int50 ) } > INT50 type = VECT_INIT
        USB_UBM      : { * ( .int51 ) } > INT51 type = VECT_INIT
        TIMER0_A1    : { * ( .int52 ) } > INT52 type = VECT_INIT
        TIMER0_A0    : { * ( .int53 ) } > INT53 type = VECT_INIT
        ADC12        : { * ( .int54 ) } > INT54 type = VECT_INIT
        USCI_B0      : { * ( .int55 ) } > INT55 type = VECT_INIT
        USCI_A0      : { * ( .int56 ) } > INT56 type = VECT_INIT
        WDT          : { * ( .int57 ) } > INT57 type = VECT_INIT
        TIMER0_B1    : { * ( .int58 ) } > INT58 type = VECT_INIT
        TIMER0_B0    : { * ( .int59 ) } > INT59 type = VECT_INIT
        COMP_B       : { * ( .int60 ) } > INT60 type = VECT_INIT
        UNMI         : { * ( .int61 ) } > INT61 type = VECT_INIT
        SYSNMI       : { * ( .int62 ) } > INT62 type = VECT_INIT
        .reset       : {}               > RESET  /* MSP430 RESET VECTOR         */ 
    }

    as you can see above, I explicitly defined the address of fn1(), fn2(), fn3() .text section (code) replacement.

    - generated MAP file:

    SECTION ALLOCATION MAP
    
     output                                  attributes/
    section   page    origin      length       input sections
    --------  ----  ----------  ----------   ----------------
    .cinit     0    00004400    00000000     UNINITIALIZED
    
    .......................
    .text:fn1 
    *          0    00006000    00000006     
                      00006000    00000006     main.obj (.text:fn1)
    
    .text:fn2 
    *          0    00008000    0000000e     
                      00008000    0000000e     main.obj (.text:fn2)
    
    .text:fn3 
    *          0    0000a000    00000006     
                      0000a000    00000006     main.obj (.text:fn3)
    .......................
    


    - generated TI-TXT file:

    @4400
    31 40 00 44 B1 13 A2 00 0C 93 02 24 B1 13 00 00 
    0C 43 B1 13 84 00 B1 13 A6 00 
    @6000
    D2 D3 04 02 10 01 
    @8000
    21 83 81 4C 00 00 1C 43 2C 51 21 53 10 01 
    @a000
    D2 E3 02 02 10 01 
    @ffd2
    9C 00 9C 00 9C 00 9C 00 9C 00 9C 00 9C 00 9C 00 
    9C 00 9C 00 9C 00 9C 00 9C 00 9C 00 9C 00 9C 00 
    9C 00 9C 00 9C 00 9C 00 9C 00 9C 00 00 44 3A 14 
    19 42 5C 01 B2 40 80 5A 5C 01 3F 40 00 00 3F 90 
    01 00 23 28 3F 40 00 00 3F 90 01 00 1E 28 3A 40 
    00 00 3A 80 00 00 3A 50 07 00 5A 09 38 40 00 00 
    3C 48 3D 48 3E 48 3F 48 C7 0C CB 0D 1C 53 0D 63 
    0F 18 4B 5B 00 18 4B D7 6B 4B 4B 4B 5B 06 00 18 
    5B 4B 00 00 4B 13 1A 83 EB 23 79 C2 39 D0 08 5A 
    82 49 5C 01 3F 40 00 00 3F 90 00 00 08 24 3A 40 
    00 00 02 3C 6A 13 2A 52 3A 90 00 00 FB 23 37 16 
    10 01 B2 40 80 5A 5C 01 B0 13 00 60 2C 43 B0 13 
    00 80 B0 13 00 A0 FF 3F 03 43 32 D0 10 00 FD 3F 
    1C 43 10 01 03 43 FF 3F 
    q
    

    I compiled this with optimization turned off, and as you can see the fn1(), and fn2(), and fn3() are fixed to the location which are defined in the linker command file.

  • Thanks Leo!.

  • Leo Hendrawan said:
    .text:fn1 : {} > 0x6000


    That's a nice idea. However, it is sub-optimal still. I tmeans the functions are linked to a specific location, but it also means that it fragments the flash memory into the gaps between the functions.
    Unfortunately, I don't know a way too to jsut define the order in which the functions are to be linked.

    Well, to define which function shall be located at bottom of flash, this is a useful trick.
    Or one puts a jumptable there that points to the functions wherever they might be. Would be nice for a dynamically loaded library.

**Attention** This is a public forum