Closed mrquincle closed 3 years ago
Some context. As you will probably know there are several segments defined for applications.
.text
segment contains the code of the program. It is written to flash and is not adjusted. If you write a new application you first erase the flash pages and then write the new program..data
segment contains initialized data. Those are typical global or static variables that have already a value assigned to them and which can typically be changed. Arguments to or variables in a function will be put on the stack
and are not part of this memory segment. This segment has to be writable as well. It is part of ram..bss
segment contains uninitialized data. This is basically the same as the .data
segment. However, it is uninitialized. It is possible that start-up code (before main) sets all these values to 0x00
, but that's not guaranteed. This segment just as .data
has to be writable during runtime.heap
which can be used to allocate data through e.g. malloc
or new
(and something like sbrk
under the hood).stack
which stores all the parameters, variables, return pointers, etc. to execute the program at runtime.It is possible to move around an application or library. Often it is assume that the .text
and .data
segments are relocated together. This is quite easy if you have virtual memory as on a Linux machine. However, on an embedded device you want control about the "distance" between the .text
and the .data
segments.
This has been added to gcc
and the conversation can be followed here. You can read how there's a -mpic-data-is-text-relative
option added. If it is disabled through -mno-pic-data-is-text-relative
it does not assume a fixed distance between .text
and .data
. The displacement is not fixed at static link time. It permits code that is PC-relative to access data in the .data
segment. It will automatically enable -msingle-pic-base
. This will use a register for PIC (program independent code) addressing. This register can also be set manually: -mpic-register=rXX
. By default the register is set to r9
if the target is EABI based or stack-checking is enabled. If not, it is set to r10
. You can read this at the gcc arm options. For completeness, EABI stands for embedded application binary interface and you've probably seen it as prefix for the compiler, e.g. arm-none-eabi-gcc
. This targets the ARM platform, has no vendor (none), and complies with the ARM EABI.
Mmm, when just calling the code, this will jump from non PIC code to PIC code, that's not gonna be pretty. Let's just for now assume that the microapp compiler fixes the location of RAM_R1_BASE
to a location between heap and stack of the main program. This is a slot it can reserve, it will not get anything else. If it wants another slot, it has to be compiled again. It's fast and easy.
This has now been tackled by coroutines implemented through my old friends setjmp and longjmp. :-)
The microapp now has a fixed location (almost) at the end of RAM. For multiple microapps it is useful to be more flexible though. Hence, the issue https://github.com/crownstone/bluenet/issues/107 has been created.
The current
microapp
will not work if there global variables defined. Both the.bss
and.data
sections are not placed properly. There are a bunch of possible flags that control various parts of the code, either on flash or in RAM:-fPIC
, for position independent code. There's nowadays also-fPIE
.-msingle-pic-base
and-mpic-register=r10
.-mno-pic-data-is-text-relative
option.Set
r10
to the proper value before themicroapp
is started.