Many compilers offer a way to allocate a variable at an absolute address. For example for the Freescale S08 compiler, I can place my variable at a given address:
unsigned char buf[128]@0x2000;
This is very useful (and needed) e.g. if the hardware (like USB) needs a buffer at given address. The advantage of the above (non-ANSI and thus not portable) syntax is that I can define a variable at an absolute address, without the need to allocate it in the linker.
I wanted to do something similar with gcc for Kinetis/ARM, and searched many forums on the internet. Obviously, I’m not alone with this question. The solution I have found comes close to what I use e.g. for the S08 compiler.
How can I place a variable say at address 0x2000’0000 with gcc for ARM/Kinetis?
The idea I use here is to put the variable with a special section name, and then place it in the linker file at an absolute address.
💡 I have not found a way to place a variable at an absolute address *without* to modify the linker file? Post a comment if you know a better solution!
__attribute__
Gcc uses the __attribute__
keyword as a way to ‘mark’ variables with special attributes. It allows me put my variable into a special section, which I name here ‘.myBufSection’:
unsigned char __attribute__((section (".myBufSection"))) buf[128];
Another useful thing is: I can specify the alignment of that variable with an __attribute__
too:
unsigned char __attribute__((section (".myBufSection"))) buf[128] __attribute__ ((aligned (512)));
With this, my variable will be put into a section named ‘.myBufSection’, and it will be aligned on a 512 address boundary.
Absolute Section Placing in Linker File
The next step is to place that section at an address in the linker file. E.g. for the KL25Z of my Freedom board, I have this memory mapping in my linker file:
MEMORY { m_interrupts (rx) : ORIGIN = 0x00000000, LENGTH = 0xC0 m_cfmprotrom (rx) : ORIGIN = 0x00000400, LENGTH = 0x10 m_text (rx) : ORIGIN = 0x00000800, LENGTH = 128K - 0x800 m_data (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K }
I could split my m_data block and create my memory block for my variable to place at 0x2000’0000. An easier way is to simply place my section from above into the SECTIONS block like this:
SECTIONS { /* placing my named section at given address: */ .myBufBlock 0x20000000 : { KEEP(*(.myBufSection)) /* keep my variable even if not referenced */ } > m_data /* other placements follow here... */ }
With above linker statement, I define an absolute start address for all my variables in the section named .myBufSection, and place it into the m_data memory block. Additionally I need to use the KEEP keyword to tell the linker *not* to dead-strip my variable, in case I do not reference it from my code.
Checking the Allocation
After linking, now my object should be at the given address. While looking at the linker map is always a good idea, I have found another nice tool which comes with the GNU suite: nm. With nm I can examine binary files like the ELF file produced by the linker. In CodeWarrior for MCU10.3, that command line utility can be found in
<CW installation path>\Cross_Tools\arm-none-eabi-gcc-4_6_2\bin\arm-none-eabi-nm.exe
I could configure to run it as post-link step in CodeWarrior, or simply use it from the DOS command line prompt:
Summary
For gcc, placing a variable at an absolute address requires two steps: marking it with a section name in the source, and then placing it in the linker file at an absolute address.
It would be good if there would be a way to avoid the linker file change, but I have not found another or better solution.
Happy Absoluting 🙂
Erich,
You are amazingly prolific!
-Bill
LikeLike
Hello Erich,
first of all thanks for the good solution!
I would like to ask this: if I need to create more than one variables ( I need few arrays..), have I to declare a section for each array? Or there is easier way, using code instead of adding more sections?
Thanks!
LikeLike
I put the question in the wrong place sorry…
LikeLike
Nope… You could use the same __attribute__((section(….)) for both…
LikeLike
*(volatile unsigned char *)(IO_BASE + 0x00)
LikeLike
Hi Barrie,
yes, using a casted pointer is the preferred way to access peripherals. The problem with this is that it is only accessing an object, but not defining it. In my case I want to reserve memory for it, not only accessing it. and if it is just such a pointer access, that will not work.
Erich
LikeLike
Is there any way of doing this while allowing Processor Expert to generate the linker file itself? I’ve had to disable “Generate Linker File” in order to maintain the modification to the linker file. Not a big deal, just curious if it’s possible. I didn’t see anything while looking through PE.
LikeLike
No, I have not found another way for this neither. I had to disable linker file generation too.
LikeLike
Pingback: GNU Linker, can you NOT Initialize my Variable? | MCU on Eclipse
Hi Erich, I’m looking for a DoOnStack equivalent for Kinetis and Google redirects here. Do you know if a DoOnStack equivalent routine exist? Thank you
LikeLike
Hi Roberto,
you mean the equivalent of AN3942 for Kinetis?
LikeLike
yes 🙂
LikeLike
I don’t have that, I guess it just would be a few hours of work 🙂
LikeLike
Eric,
i am using your post for embedding a version inside the output file.
i did as you have described:
in the linker script:
.myBufBlock 0x00000000 : {
KEEP(*(.myBufSection))
} > DDR2_SDRAM_MEM_BASEADDR
in the code:
int __attribute__((section (“.myBufSection”))) SWVersionInFile = 0x0306060A; // 3.6.6.10
the problem that in the output file itself, the data is placed as ASCII and not as its value.
meaning that the values looks like that:
30 33 30 36 30 36 30 41
instead of::
03 06 06 0A
Where is the problem?
Thanks.
LikeLike
Hi shurik,
hmm, that’s really strange. I tried to replicate this, and added this to my .text section:
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP(*(.myBufSection))
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
but for me the result was as expected (0x306060a). Could it be that you look at the wrong variable? Can you verifiy in the linker map file that your variable has indeed be linked (and not be removed by the linker as not used?).
LikeLike
Simpler solution: just declare the variable as extern and assign an absolute value to that symbol in your linker script.
LikeLiked by 1 person
Can you share such an symbol entry in your linker script?
LikeLiked by 1 person
SECTIONS {
buf = 0x20000000;
/* other stuff */
}
LikeLike
That’s indeed very simple, I had not considered this, thanks for sharing!
LikeLike
See also https://sourceware.org/binutils/docs-2.24/ld/Assignments.html
LikeLike
Thanks, that link helps even better to understand how it works 🙂
LikeLike
Actually I discovered it’s even simpler: you can just put a bunch of assignment statements in a file and pass it to the linker as if it’s an object file. This works regardless of whether you also have a custom linker script, and you can pass multiple of such files if you wish.
LikeLike
Erich should write all the Kinetis docs. This is great.
LikeLike
Hello Erich,
first of all thanks for the good solution!
I would like to ask this: if I need to create more than one variables ( I need few arrays..), have I to declare a section for each array? Or there is easier way, using code instead of adding more sections?
Thanks!
LikeLike
Found it 🙂
u simple declare the second array just after the first one, with the same __attribute__((section (“.myBufSection”))).
The linker will put the second array in the location just after the first one.
LikeLike
I do not believe that there’s any guarantee that they will end up in memory in source-order. See however my (simpler) alternative method in the comments above; you can just do
buf = 0x20000000;
buf2 = buf + 0x1000;
or whatever. BTW, I put them in a SECTIONS { } block above, but that actually turns out to be optional. You can just put assignments like those in a text file named “whatever.ld” and provide it to ld or even to gcc as a source file (or rather, it is treated as an object file of a slightly strange sort).
LikeLike
For having the variables in the same source order you can use a structure. And if you want them on the same order and without wasted space because of padding then you can use a PACKED structure. That way you guarantee the order along with the position in memory.
LikeLike
Thank you very much, it is very helpful!
LikeLike
I wonder if I can use this technique so I can make use of the 832-byte memory area in the KL05 that occupies the space between the end of the m_interrupt area at address 0xc0 and the 16-byte “Flash Configuration Field” – fixed at address 0x400. This appears to be wasted. Can I set m_text start address to 0xc0 simply tell the linker to place the Flash Configuration Field (defined as _cfm[] in Cpu.c) at 0x400?
I tried to copy your example and ended up with _cfm correctly at 0x400, but none of the space between 0xc0 and 0x400 was used.
LikeLike
Yes, I think you should be able to do this, but have not done this myself.
LikeLike
An example for ARM:
asm (“.set mivar, 0x1234”);
extern int mivar;
main(int argc, char **argv)
{
mivar=0x4567;
}
This is the code generated:
00008018 :
8018: e59f2008 ldr r2, [pc, #8] ; 8028
801c: e59f3008 ldr r3, [pc, #8] ; 802c
8020: e5832000 str r2, [r3]
8024: e12fff1e bx lr
8028: 00004567 .word 0x00004567
802c: 00001234 .word 0x00001234
LikeLike
Hi Jesari,
oh wow, that’s a VERY neat way of doing this! Thanks for sharing!
LikeLike
You’re welcome.
BTW, you may also consider to include the following asm line if you’re going to reference the absolute variable from a different source file:
asm (“.global mivar”);
The main problem I’m seeing with this solution is the lack of portability due to the different assembler directives for other architectures.
LikeLike
What an ugly hack, but so easily solves all problems of making constant values computed using a C++ `constexpr` usable in ASM code by passing them though the linker. Thanks!
For others in the future, some versions of gcc also provide `#pragma LOCATION(address)` and/or `__attribute__((location(address)))` to specify the address to put a variable, which is slightly cleaner if available….
https://downloads.ti.com/docs/esd/SLAU132/the-location-pragma-stdz0559880.html
LikeLike
I agree, that __attribute__((location(address))) would be the way to go. But so far I have seen this only in the TI version of gcc, and not for other architectures?
LikeLike
Correct, I have not seen it anywhere else besides the TI compiler and even there it is proving to be quite flakey. Sometimes code will compile and link with no errors or warnings, but the variable will inexplicably end up at address `0x0001`.
Sadly in my case I think I am going to have to resort to code-that-writes-code; write a C++ program that emits ASM source with hard coded address constants which is then assembled into an OBJ that is linked back into the final program. Not happy about it though.
LikeLike
Using the __attribute__((section (“.mysectionName”))) worked very well for me. So far I have just tweaked the linker file for it, and that was not hard. I was considering writing a small script to make a linker script file I could include into the linker script, but so far it was easier to do it by hand.
LikeLike
Thanks for the information. I tried both methods above and my variable is indeed at the location I want, however the linker also put another variable at the same location. This is verified by seeing the other variables address in both the map file as well as in the watch window. Any suggestions?
LikeLike
Hi Larry,
you would need to exclude that memory area in your linker script file.
LikeLike
Hi Erich,
I have meet same question, could you tell me how to exclude that memory area. I have search in some link script document, but could not find the answer.
LikeLike
Hi cai,
Have a look at the MEMORY section in the linker file: you can reduce the section size and create additional sections.
Erich
LikeLike
Hey Erich
Awesome Solution. Now We know how to place a variable in a specific location. But If I want to place a piece of code in a specific memory address. What should I do ?
unsigned int i;
for(;;){
Bit1_ClrVal(); // passing ‘0’ to CR1 LED port
for(i=0;i<=1000000;i++); //software delay
Bit1_SetVal(); // passing '1' to CR1 LED port
for(i=0;i<=1000000;i++); //software delay
}
I want to put this code into the flash memory area of my KINETIS E series controller (MKE02Z64VLD2). Flash region is 0X0000_0000 to 0X07FF_FFFF. Can u say how it is done ?
Thanks
Regards
Ganesh R
LikeLike
Hi Ganesh,
the easiest way is to do this in the linker file, and per file. See https://mcuoneclipse.com/2014/10/06/putting-code-of-files-into-special-section-with-the-gnu-linker/
Otherwise you need to mark each function with a section attribute and then handle it in the linker file.
Erich
LikeLike
Thanks a ton for this post! I need to be able to reprogram data in non-volatile memory, and my chip can only do that 4kB at a time. I can’t mess with the execution instructions that the data used to be mixed in with, so I can’t just use an absolute pointer as others suggested. I need a section of ROM that I know I can mess with without interrupting operation of the device.
LikeLike
Yes, depending on the FLASH technology 1, 2, 4, 8 or more are in a block/sector. I have used sucessfully used the approach I have described in https://mcuoneclipse.com/2014/05/31/configuration-data-using-the-internal-flash-instead-of-an-external-eeprom/
LikeLike
Erich, is there a way to get the base address for a section that is defined in the linker script (like the .myBufSection you created in your example above), if for example, you wanted to read a few bytes starting from the beginning of this section ?
LikeLike
Hi Geoff,
yes, there should be a way, at least for the section name, maybe with an additional label in the linker script. I’m travelling today, but I see in the evening/tonight if I could write up something small on that topic.
Erich
LikeLike
to close the loop: new article published on that topic: https://mcuoneclipse.com/2016/11/01/getting-the-memory-range-of-sections-with-gnu-linker-files/
LikeLike
Pingback: Accessing GNU Linker Script Symbols from C/C++ | MCU on Eclipse
Pingback: Flash-based Configuration Data Using The ld Linker – vilimblog
I have two comments to add:
1. Given this code:
unsigned char __attribute__((section (“.myBufSection”))) buf[128] __attribute__ ((aligned (512)));
I think it can be written in a shorter manner by separating the attributes with a comma:
unsigned char __attribute__((section (“.myBufSection”), aligned (512))) buf[128];
2. By using the “used” attribute, GCC is explicitly told not to dead-strip the variable when not referenced. I think it’s similar to the KEEP() directive of link scripts:
void __attribute__ ((used, section (“.init3”), naked)) move_sp(void) {…}
LikeLike
Yes, __attribute__ settings can be combined, but sometimes they have be before or after a declaration. I have not checked in that particular case if both can be before the declaration.
The used attribute is something too, but to my knowledge it is working for functions only, but not for variables. That way the KEEP inside the linker script is very useful.
LikeLike
Thanks for the correction on both accounts, Erich! It’s always great to learn new stuff from you. 🙂
LikeLike
Thank you very much Erich! This is a great thing and helps a lot! I’ve tested it with success in debug mode. If I switch to Release it doesn’t work any more. I found out the reason: Debug Setting -> Optimization Level: None, Release Setting -> Optimization Level: Optimize for size. If I change this in Release mode it works well again. But I have bigger code-size. I thought the KEEP instruction in the linker script would prevent this? Or am I doing something wrong?
Regards, Dirk
LikeLike
Hi Dirk,
strange, it works for me regardless of optimization level. Maybe it depends on the GNU compiler version (have not checked), but in KDS it works with GNU ARM Embedded 4.8 Q3 2014.
You might have a look at one of my example projects, e.g. https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-KL03Z/FRDM-KL03Z_LED. The variable bootloader_config_t inside the bootloader_config.c is preserved.
LikeLike
Hello Erich, thank you for your reply. I have already looked into your source code, but have not yet come across something that helped. The development environment is Infineon DAVE 4.3.2 (ARM-GCC-49). The Device: XMC4500. I will continue looking for a solution. If I have it, set it here as well. Thanks, Erich! Regards, Dirk
LikeLike
Pingback: Getting Started: ROM Bootloader on the NXP FRDM-KL03Z Board | MCU on Eclipse
Pingback: Using Multiple Memory Regions with the FreeRTOS Heap | MCU on Eclipse
A really nice explanation about this topic, I don’t like the method but guess there is not other way to do it. Thanks
LikeLike
I’m not aware of any other or better way.
LikeLike
I have also used the flag -fdata-sections and while it still requires linker magic, it avoids the need for the attributes in the source code. It also will allow you to order specific declarations in a section if needed.
LikeLike
The -fdata-sections flag basically means that the linker creates a section name for each variable. That way the name of that section or variable can be used in the linker file. That’s indeed another good approach.
LikeLike
Why can’t be simply done like this:
DIM var AS [XRAM/SRAM/ERAM]type [AT location/variable] [OVERLAY]
https://avrhelp.mcselec.com/index.html?dim.htm
I think, Bascom solution is the best and most elegant. Does exist something like this for C – ARM? Is C stupid or me? How to improve C? How to translate such code to C? I start learn C and would really like to hear opinions.
LikeLike
That example is with BASIC, and the concepts are really different to the C language. C has a long heritage plus must conform to standards which might be counter intutitive. On the plus side: C (and C++) are close to the hardware so you can know what happens for every line of your program. And you get C for virtually any architecture/CPU/microcontroller where Bascom is more of a nice solution to me? I think you have to go through that learning experience, I’m affraid.
LikeLike
Pingback: Stack Canaries with GCC: Checking for Stack Overflow at Runtime | MCU on Eclipse
If I create a section at the end of .text, this is, if .text is declared having a size of 0x8000 and I “resize” .text to 0x7FC00 (assuming a flash sector of 1K), and create my section starting on 0x7FC00 with a size of 0x400 (1k), is the flashing tool not going to touch this section?
I ask because I want to use this portion of memory at the end of .text to store non-volatile data and it is not desirable at all that the flashing tool would wipe it out, but I’m not sure if I have to do any additional steps or add additional declarations to the linker file or the project to keep the flashing tool from touching this area.
LikeLike
If an area is erased or not depends on multiple factors:
– debug probe: some debug probe will erase the whole device (all sectors), some only the sectors which are part to the binary. Some have a setting to configure this
– on chip/bootloader: usually you can define which sectors are erased (or protected)
The linker itself does not control this: all what it does is to build the binary
LikeLike
That would be flash tool dependant. Some erase the entire chip and some you can specify what range to erase. Even in that case some will erase the chip and then restore the preserved areas back. A linker script change will not necessarily help you here.
LikeLike
Hi,
How do I write the same thing as this:
”
#pragma location = “OPTBYTE”
__root const char opbyte0 = 0xFF;
#pragma location = “OPTBYTE”
__root const char opbyte1 = 0xF3;
”
but with gcc?
Im trying to build this code in e2 studio but i keep getting a lot of erros
thank you
LikeLike
I have not worked with e2 studio recently, but as it uses GNU/gcc you should use the __attribute__ syntax.
LikeLike
To access a struct at some fixed address, just use a pointer whose value is the address:
struct type_t *varp = (type_t *)0x200000;
I suppose this might not work in some environments but it’s what I do when I need.
LikeLike
Hi Joe,
yes, that’s the normal way for accessing hardware/etc which are already at a fixed address, or if an object has an address. The bigger problem is how to place an arbitrary object at a specific address (not necessarily accessing it).
LikeLike
Hi,
If the problem is the selection of a RAM region to store a heap (FreeRTOS heap for example), there is a simpler mean with mcuxpresso IDE to do the stuff without writing custom linker script (or changing the generated one).
If for example I have:
uint8_t __attribute__((section (“.mySection”))) ucHeap[ configTOTAL_HEAP_SIZE ];
Then in Project/properties/C/C++ Buid/Settings/MCU Linker/Managed Linker Script, there is “Extra linker script input sections” where in the
“Input section description” field I can put *(.mySection)
“Region” I can select one of my uC region listed
“Section Type” select .bss
Regards,
Olivier
LikeLike
Hi Oliver,
thanks! I’m using the same approach for my FreeRTOS heap allocation where I use an already existing section name by default.
Good hint about the ability to add your own section that way, I like that!
Erich
LikeLiked by 1 person
Thanks for sharing!
LikeLiked by 1 person
You are welcome!
LikeLike