Hello,I want to keep some variables in my code at certain addresses. For this, I created a new section in the LD file to reserve a certain area from the existing FLASH memory. I wait for the variable I created by typing __attribute__((section(".flash_rw.__at_0x000...))) to write to the address I specified. However, it writes the value to a completely different address in the section I created. I use arm-none-eabi-. GNU Arm Embedded Toolchain version 10 2021.10.
MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x40000 /* 256 KB ana Flash bellek */ FLASH_RW (rx) : ORIGIN = 0x00040000, LENGTH = 0x40000 /* 256 KB yazılabilir Flash bellek */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x18000 /* 96 KB RAM */ }
SECTIONS { .... .... .... .... .flash_rw : { . = ORIGIN(FLASH_RW); __flash_rw_start__ = .; *(.flash_rw) *(.flash_rw.*) . = ALIGN(4); __flash_rw_end__ = .; } > FLASH_RW
unsigned short tristor50x35[584] __attribute__((section(".flash_rw.__at_0x0006A4CA"))) = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x820, 0x842, 0x842, 0x842, ........ };
The output of the code is as follows;
Flash Address tristor50x35 => 0x00057b70
-
Yes, there are about 50 icon arrays like this. It places them according to the line order I wrote, starting from 0x40000. thyristor50x35 is exactly where it should be on the output. But I want to manually determine the address of each icon array. like 0x6A4CA for thyristor.
Then I will have to write this to the ld file for all icons. And when I add a new icon, I will need to add it there. Would this make sense?
Looking at this thread:Yea, the 0x00057b70 was likely just because of automatic placement of all your "*(.flash_rw.*)" after ORIGIN(FLASH_RW). I don't know how that's determined tbh, if that is alphabetical or not, but it's best to assume it's random and then explicitly specify the sections you care about, so that they always end up in the right place.as I mentioned in the other thread, the __at_ is an Arm-Compiler only feature that relies on `armlink` and scatter files. With ld or lld and linker scripts this feature doesn't exit and you have to indeed do this manually in the linker script.Something I've never tried but might be worth trying:If you have a addresses.h header file, I wonder if you can use it in both C source code and in the linker script, e.g.:<<<< edited out, correct ones are below>>>
Although you may need some hacky C preprocessor-concatenating...EDIT:::
addresses.h:
#define _STRINGIFY(x) #x #define STRINGIFY(x) _STRINGIFY(x) #define _CONCATPREFIX(y) __arm_at_##y #define ARM_AT_ADDR(y) STRINGIFY (_CONCATPREFIX (y)) #define ADDR50X35 0x0006A4CA << all your other addresses here >>
int __attribute__((section(ARM_AT_ADDR (ADDR50X35)))) test2 = 1 ;
.abs_thyristor ADDR50X35 : { *(ARM_AT_ADDR(ADDR50X35))}
non constant or forward reference address expression for section .abs_tristor50x35
.flash_rw : { . = ORIGIN(FLASH_RW); __flash_rw_start__ = .; *(.flash_rw) *(.flash_rw.*) . = ALIGN(4); __flash_rw_end__ = .; } > FLASH_RW .abs_tristor50x35 ADDR_TRISTOR : { *(.flash_rw.__at_ADDR_TRISTOR) }
#define ADDR_TRISTOR 0x0006A4CA unsigned short tristor50x35[584] __attribute__((section(".flash_rw.__at_ADDR50X35"))) = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ..... };
I got an error like this.EDIT:
.flash_rw : { . = ORIGIN(FLASH_RW); __flash_rw_start__ = .; tristor50x35 = .; . += 1168; /* reserve 1168bytes for tristor50x35 */ . = ORIGIN(FLASH_RW) + 0x20000; /* 0x40000 + 0x20000 = 0x60000 */ tristor50x35 = .; *(.flash_rw) *(.flash_rw.*) . = ALIGN(4); __flash_rw_end__ = .; } > FLASH_RW unsigned short tristor50x35[584] __attribute__((section(".flash_rw"))) = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x820, 0x842, 0x842, 0x842, }; output => Flash Address tristor50x35 => 0x00060000 It was solved this way. It will be a bit challenging for all the variables.
First of all, in the situation that I mentioned in my last article, the icons were not appearing on the TFT screen.
//icons.h #define _STRINGIFY(x) #x #define STRINGIFY(x) _STRINGIFY(x) #define _CONCATPREFIX(y) __arm_at_##y #define ARM_AT_ADDR(y) STRINGIFY (_CONCATPREFIX (y)) #define ADDR50X35 0x0006A4CA
//icons.c unsigned short __attribute__((section(ARM_AT_ADDR (ADDR50X35)))) tristor50x35[584] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x820, 0x842, 0x842, 0x842, . . . };
I ran the command you said and created a new ld file. and I use this as linker but =>
ignoring invalid character `\377' in expression ignoring invalid character `\376' in expression ignoring invalid character `\000' in expression
I am getting error like this.
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") .flash_rw : { . = ORIGIN(FLASH_RW); __flash_rw_start__ = .; *(.flash_rw) *(.flash_rw.*) . = ALIGN(4); __flash_rw_end__ = .; } > FLASH_RW .abs_tristor50x35 ADDR50X35 : { *(ARM_AT_ADDR(ADDR50X35)) } }
Sadly I have no idea what those "invalid character" error messages are! Did you #include <icons.h> in your LD script before preprocessing it?I would expect the " .abs_tristor50x35 ADDR50X35 : { *(ARM_AT_ADDR(ADDR50X35)) }" line to now feature the 0x0006A4CA after preprocessing
First of all, when preprocessing as lscript.ld, it gives an error because #include "icons.h" cannot be found. So I changed the extension of the ldscript.ld file to ldscript.c. Likewise, there is the #include section at the beginning and under it are the linker script settings. The command I just ran is
arm-none-eabi-gcc -P -E ldscript.c > ldscript.ld
However, after this command, I received an invalid character error. this is because a problem with encoding. To solve this, I changed the command like this
arm-none-eabi-gcc -P -E ldscript.c | % {$_ -replace "`r`n","`n"} | Out-File -Encoding ascii ldscript.ld
and the problem was solved. However, I could not run it with #define's as you said. Instead, addresses are defined one by one in the ldscript.c file, and the preprocessing process must be repeated for each address change.
// ldscript.c file #include "icons.h" #define tristor50x35 0x65C00 MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x40000 /* 256 KB */ FLASH_RW (rx) : ORIGIN = 0x00040000, LENGTH = 0x40000 /* 256 KB */ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x18000 /* 96 KB */ } SECTIONS { //other parts .flash_rw : { //flash_rw section } > FLASH_RW .abs_tristor50x35 tristor50x35 : {*(.flash_rw.__at_tristor50x35)} }
ld file created after preprocessing;
.flash_rw : { . = ORIGIN(FLASH_RW); __flash_rw_start__ = .; *(.flash_rw) *(.flash_rw.*) . = ALIGN(4); __flash_rw_end__ = .; } > FLASH_RW .abs_tristor50x35 0x65C00 : { *(.flash_rw.__at_tristor50x35 ) }
Ok, interesting. There definitely must be something funky going on with your editor or operating system for the non-ascii characters to be creeping in. I suspect if you find out what that is and that all files start with the correct ASCII characters, then the on-the-fly replace and encoding change won't be needed.Another tip:"-x c " If you add that to your command line to the preprocessor it tells it to treat the input file as C code, regardless of the file extension. Then you won't need to go through renaming to ldscript.c.
What I was aiming for is a world where:* icons.h contains the definitions for STRINGIFY, ARM_AT_ADDR, etc. and all the address definitions, e.g. "#define tristor50x35 0x65C00"
* your original ld script only #includes icons.h. It then uses the preprocessor macros in the SECTIONS command.
* your C code also only #includes icons.h and uses the preprocessor macros in the __attribute__(section)).The benefit of this is that you end up defining the addresses in one place, rather than in multiple places. As such, you can more easily move things around in the memory map, and you have less of a maintenance burden when you want to change something