Hi there,
Can I link specific section at the start of FLASH code memory?
Thanks in advance!
With best regards,
Rahul
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.
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
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.
Leo Hendrawan said:.text:fn1 : {} > 0x6000
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