I am currently trying to reserve a sector of the flash memory in the linker file, to save some data to it (using the driverlib API). I first flash the script writing to the specific memory addresses, then I run my application which reads the saved data.
Unfortunately whenever I flash, the data is lost. Therefore I am trying to change the linker file and reserve some space but I am not sure if I am doing it correctly. I will appreciate any help or hints.
MEMORY
{
/* Flash Size 128 KB minus the CCA area below (88 bytes) */
/* OLD: FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x0001FFA8 */
FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x0001FF88
/*
* Custom reserved memory space with size of 32 bytes
*/
CNVM (RX) : ORIGIN = 0x0001FF88, LENGTH = 32
/*
* Customer Configuration Area and Bootloader Backdoor configuration
* in flash, up to 88 bytes
*/
FLASH_CCFG (RX) : ORIGIN = 0x0001FFA8, LENGTH = 88
/* RAM Size 20KB */
SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00005000
/* Application can use GPRAM region as RAM if cache is disabled in CCFG */
GPRAM (RWX) : ORIGIN = 0x11000000, LENGTH = 0x00002000
}
/*. Highest address of the stack. Used in startup file .*/
_estack = ORIGIN(SRAM) + LENGTH(SRAM); /* End of SRAM */
/*. Generate a link error if heap and stack don’t fit into RAM .*/
_Min_Heap_Size = 0;
_Min_Stack_Size = 0x100;
SECTIONS
{
.text :
{
_text = .;
KEEP(*(.vectors))
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH = 0
.text:
{
*(.rodata*)
} > CNVM
.data :
{
_data = .;
*(vtable)
*(.data*)
_edata = .;
} > SRAM AT > FLASH
.ARM.exidx :
{
*(.ARM.exidx*)
} > FLASH
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > SRAM
.ccfg :
{
KEEP(*(.ccfg))
} > FLASH_CCFG
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} > SRAM
.gpram :
{
} > GPRAM
}
Using the linker approach didn't provide the desired result in my case. What I ended up doing instead is editing the generated binary file from my code before flashing the sensortag.
Using the hexdump command on linux as follows hexdump generated_binary_file.bin one can notice that each line includes the start memory address (for a certain range of addresses) followed by the data written to this range.
And so using a small python script one can change the values in a certain line and generate its own modified binary file that will be later flashed to the sensortag. The memory address content can be read with a certain function that you include in your initial code (before bin generation & editing) such memcpy() for example.
Related
We are having some troubles with variables stored in SRAM and default values.
We are working with a STM32F745ZE micro. We had to define a section for SRAM:
/* Specify the memory areas */
MEMORY
{
ITCM_RAM (rx) : ORIGIN = 0x00000000, LENGTH = 16K /* +MW+ */
/*RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 319K*/
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* +MW+ DTCM RAM */
RAM_GEN (xrw) : ORIGIN = 0x20010000, LENGTH = 255K /* +MW+ SRAM1 + SRAM2 */
TRACER (xrw) : ORIGIN = 0x2004FC00, LENGTH = 1K /* +MW+ TRACER memory space */
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K
}
(...)
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* +MW+ SRAM data section */
.ram_gen :
{
. = ALIGN(4);
_sram_gen = .; /* create a global symbol at data start */
*(.ram_gen) /* .data sections */
*(.ram_gen*) /* .data* sections */
. = ALIGN(4);
_eram_gen = .; /* define a global symbol at data end */
} >RAM_GEN
We want to assign default values to some varieables. It works fine for variables not stored in SRAM, but it doesn't work for varaibles stored in SRAM:. Example
static Test_Ram_t testRam = { .value = 1 };
static Test_Ram_Value_t testRamValue __attribute__((section(".ram_gen"))) = { .value = 1 };
static void Test_Ram_Task1(void const *pvParameters)
{
Test_Ram_Printf("Test Ram: START -----------------------------------------------");
Test_Ram_Printf("Test Ram: Pre value: %d %d", testRam.value, testRamValue.value);
testRam.value += 10;
testRamValue.value += 10;
Test_Ram_Printf("Test Ram: Post value: %d %d", testRam.value, testRamValue.value);
osDelay(osWaitForever);
}
If we reboot the application 3 times the application output is:
[10:30:25.002]
[10:30:25.004] Test Ram: START -----------------------------------------------
[10:30:25.005] Test Ram: Pre value: 1 1
[10:30:25.005] Test Ram: Post value: 11 11
[10:30:27.599]
[10:30:27.601] Test Ram: START -----------------------------------------------
[10:30:27.603] Test Ram: Pre value: 1 11
[10:30:27.604] Test Ram: Post value: 11 21
[10:30:29.497]
[10:30:29.500] Test Ram: START -----------------------------------------------
[10:30:29.502] Test Ram: Pre value: 1 21
[10:30:29.503] Test Ram: Post value: 11 31
Varaible testRam, stored in RAM, is assigned the default value in every restart, but varaible testRamValue, stored in SRAM, the value is keeped between reboots.
Does anyone know how to force to assign the default value on every reboot?
I have a linker script for an embedded system that's doing some relocations (code that is loaded onto the flash of the device, but copied to RAM on boot for execution). It's using the AT feature of the linker, which seems designed to do this.
The problem is that the size of the relocation section is currently only charged to the ram memory region, when in practice it should be charged to both the rom and ram regions (it occupies the former when the device is at rest and the latter when it's active). Currently, if the data alone fits in rom but the data + relocation exceeds rom, you won't get any errors or warnings.
How do I get the .relocate section to charge its size to both the rom and ram memory regions?
Minimalized linker script:
MEMORY
{
rom (rx) : ORIGIN = ROM_ORIGIN, LENGTH = ROM_LENGTH
ram (rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_LENGTH
}
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x1000;
SECTIONS
{
.text :
{
. = ALIGN(4);
_stext = .; /* First of standard s,e (start/end) pair */
KEEP(*(.vectors .vectors.*))
KEEP(*(.irqs))
*(.text .text.* .gnu.linkonce.t.*)
*(.rodata .rodata* .gnu.linkonce.r.*)
} > rom
/* Mark the end of static elements */
. = ALIGN(4);
_etext = .;
/* This is program data that is exepected to live in SRAM, but is
* initialized with a value. This data is physically placed into flash and
* is copied into SRAM at boot. The symbols here will be defined with
* addresses in SRAM.
*
* This is the section that needs to be charged to BOTH rom and ram */
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
.sram (NOLOAD) :
{
. = ALIGN(8);
_sstack = .;
. = . + __stack_size__;
. = ALIGN(8);
_estack = .;
/* BSS section. Memory that is expected to be initialized to zero. */
. = ALIGN(4);
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ezero = .;
} > ram
}
Or here is the complete linker script file.
We managed to solve this. The solution is to change how the location of the relocate section is specified, specifically, this is wrong:
# Bad:
.relocate : AT (_etext)
{
...
} > ram
Rather, the AT directive should go at the end, like this:
# Correct
.relocate :
{
...
} > ram AT > rom
This will cause the linker to charge the size of .relocate to both ram and rom, while placing the section "physically" in rom.
(Final applied patch to the full linker script linked in the question)
I have an embedded system that I am designing using a GNU toolchain. One of the requirements is that it needs to calculate the checksum of the executable code (ROM) at runtime, and compare it to a known value. Depending on weather the calculated value is equal to the known value it will throw an error or not. I need to place the known value in flash memory( where my executable code is stored) in a way that won't change the executable code. AKA I cannot write the value to the flash in my executable code.
I know there are tools that can modify output files to place a checksum in a known address, but for IT reasons external tools are not an option. I decided to use the SHORT() command in the linker and just edit the linker to place the known checksum in a known address at write time. It is not working, and I do not know why.
Relevent Portions of the Linker Script I have:
MEMORY {
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
m_interrupts_ram (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x00000400
m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x000FFBE0
m_data (RX) : ORIGIN = 0x1FFF0400, LENGTH = 0x0000FC00
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00030000
}
SECTIONS
{
.text :
{
. = ALIGN(4);
*(.fill)
*(.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 (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
.... More similar sections
....down at the bottom right before stack/heap definition
__ChecksumStart = 0xFFFE0;
.checksum : AT(__ChecksumStart)
{
. = ALIGN (0x4);
SHORT(0xABCD)
} > m_text
__ChecksumSize = SIZEOF(.checksum);
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
} > m_data_2
.stack :
{
. = ALIGN(8);
. += STACK_SIZE;
} > m_data_2
__StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
.ARM.attributes 0 : { *(.ARM.attributes) }
} //end of SECTIONS block here
I should be able to look at location 0xFFFE0 in my executable code and see 0xABCD. I do not. I see 0xFFFFFFFF the default value. What do I need to change to make this work? I have looked at this tutorial to get this far
I have to place array at specific address in memory. I'm using GCC.
I declare variable like this:
uint8_t __attribute__((section (".mySection"))) buffer[1234];
And in linker script I've got:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 145K
MYSEC (x) : ORIGIN = 0x20025000, LENGTH = 155K
}
and later:
.mySection :
{
*(.mySection);
} > MYSEC
It's of course code for embedded system (ARM). Normally my program takes 22 KB, with this modification it takes 384 MB (!).
I don't understand why. If I remove __attribute__ it takes 22 KB again.
What am I missing?
Code used:
#inculde (...)
uint8_t __attribute__((section (".mySection"))) buffer = 5;
int main(void){
buffer = 10;
}
Full linker script (default, not written by me, parts are shortened:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20050000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 145K
MYSEC (x) : ORIGIN = 0x20025000, LENGTH = 155K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
(...)
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
(...)
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
(...)
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
(...)
} >FLASH
.preinit_array :
{
(...)
} >FLASH
.init_array :
{
(...)
} >FLASH
.fini_array :
{
(...)
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
(...)
} >RAM AT> FLASH
.mySection :
{
*(.mySection);
} > MYSEC
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
(...)
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
(...)
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
(...)
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
I assume your output file is a pure binary format, not an ELF so you don't have ELF bootloader. In that case, placing initialized data at high address obviously will create a big output file. This is because in the binary format you don't have any mechanism to provide specific address, so the file is mapped 1:1 into memory. It means the whole address space up to your custom initialized variable needs to be included in the output file.
This is the same situation as with .data section and this is why the .data section is explicitly copied from Flash into RAM area at the startup.
p.s. You can find my article helpful (this issue is described there).
So, I have this linker script:
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
SECTIONS
{
.kernel.text :
{
_kernel_text = .;
KEEP(kernel.a(.isr_vector))
KEEP(kernel.a(_sbrk))
kernel.a(.text*)
kernel.a(.rodata*)
_kernel_etext = .;
_kernel_flash_data = ALIGN(0x4);
} > FLASH
.kernel.data : /*AT(ADDR(.text) + SIZEOF(.text))*/ /*contains initialized data*/
{
_kernel_data = .;
kernel.a(vtable)
kernel.a(.data*)
_kernel_edata = .;
} > SRAM AT > FLASH
.kernel.bss :
{
_kernel_bss = .;
kernel.a(.bss*)
kernel.a(COMMON)
_kernel_ebss = .;
} > SRAM
.core.text : ALIGN(0x1000)
{
_core_text = .;
core.a(.text*)
core.a(.rodata*)
_core_etext = .;
_core_flash_data = ALIGN(0x4);
} > FLASH
/* There is lots more, but this is the interesting part */
}
And lets focus on the flash. The flash starts at 0x0 and first the entire kernel.text is written to it, then kernel.data is written to it. And I want a MPU to protect this memory region. This MPU can only work on memory sections with a size of a power of two. I want the entire kernel section in the flash (data + text) to be protected under a single region by the MPU, so I need its total size to be a power of two. The align command on .core.text will do this for me, for now. I know for a fact that .kernel.text + .kernel.data = 3960 bytes long, so I want to align to 2^12 = 4096 = 0x1000. Now I can protect from 0x0 to 0x1000 under a single region and protect the kernel under a single MPU region. Party on!
But the project is far from done and code will be added, so we might cross this boundry. The first time this is not a problem: the memory will align to the next 4096 barrier, which is 8192 and 2^13. But after that, the memory will align to 12288, which is not a power of two, so my MPU will spit at me and scoff me.
Is there a way to make this linker script always align to the next power of two?
Thankfully, GNU ld provides a handy-dandy log2ceil() function for instances just like this. Simply write your linker script as follows:
/* ... */
_flash_text_data_end_aligned = (2 << LOG2CEIL( _etext + SIZEOF(.data)));
/* ... */
.core.text: ALIGN(_flash_text_data_end_aligned)
/* ... */