Hi
I want to create a position independent application in Keil for an EFM32 device (Cortex-M3). The application should be loaded by a bootloader. I use the ROPI option when compiling the C-code and the bootloader takes care of updating the interrupt vectors.
The problem I have is that the startup code (__main) still seems to use fixed addressing. Is there a way to make __main position independent or is there another startup function I can use?
Best regards Filip
Aren't all the vectors pointing to absolute/fixed addresses? So no relative/address-independence there.
Put the address of main() or __main() or whatever in you vector table, and jump to that, if you're got that issue solved.
All the vectors point to fixed addresses, which is why the bootloader takes care of updating them when the application is uploaded (the bootloader will add the address offset to each of the interrupt vectors).
The problem is that you need to run __main in order to initialize such things as static variables or code that is running from RAM before calling main(). All toolchains provide such startup functions and Keil is no exception. The problem is that the default implementation of __main is not compatible with position independent code. It uses fixed addresses and consequently jumps out of the application region when the application is written to a higher memory address.
Which is why one typically links the boot loader to run at 0x08000000, and the application to run at, say, 0x08004000 and then relocate the vector table (SCB->VTOR) and jump to the new SP/PC
Alternately you can take your startup.s (or whatever) and park BSS initialization pointers in there, or via the scatter file (linker script), in a fashion your boot loader can fix up. This does however seem an unnecessary amount of work for a simple boot loader / app pairing.
You could implement your own C Runtime startup code to replace __main,etc and jump directly to main() once you've initialized the environment/arena correctly.
Do you have multiple applications driving the address independence quest?
> The problem is that the default implementation of __main is not > compatible with position independent code.
Are you building all of the application with --apcs=/ropi and linking with --apcs=/ropi? If so then __main and the stuff it calls should also be position-independent.
I am compiling with --acps=/ropi. If I tick the box "Make RO sections position independent" the IDE inserts --ropi for the linker. If I then try to link I get this error.
Warning: L6914W: option ropi ignored when using --scatter.
I have tried inserting "--apcs=/ropi" in the Misc Controls field for the linker. It then links, but the __main code still jumps out of its bounds.
Yes, you're right, I meant pass "--ropi" to armlink, (not "--apcs/rpoi").
Since you're using a scatter file you can't use --ropi. You need to mark the execution region as "PI" in the scatter file. E.g. instead of
LOAD_ROM 0 0x8000 { EXEC_ROM 0 0x8000 { * (+RO) ; Place all code and RO data into ; this exec region } ... }
have something like
LOAD_ROM 0 0x8000 { EXEC_RAM 0 PI 0x8000 { * (+RO) ; Place all code and RO data into ; this exec region } ... }
With the changes in the scatter file I made it work. Thank you so much for your help!
Glad to hear it. Your thanks are why people like me read and post here. That and the chance to show off :-)
Hi,
I am reopening this thread as I am having a problem similar to Clive's one. I am working on the STM32F207 Keil development board and I am also having trouble getting the __main compatible with position independence. For example, in the __scatterload we can read such assembly instructions:
BNE 0x0800001E
which is not very nice when you want position independent code. Has anyone got an idea?
PS: Here are some linker error examples I am getting:
.\build\Blinky.axf: Error: L6248E: startup_stm32f2xx.o(.text) in PI region 'ER_IROM1' cannot have address type relocation to __main in PI region 'ER_IROM1'. .\build\Blinky.axf: Error: L6285E: Non-relocatable Load region LR_IROM1 contains R-Type dynamic relocations. First R-Type dynamic relocation found in startup_stm32f2xx.o(.text) at offset 0xe4.