Gcc for ARM - moving code and stack

I am working on a project for ARM Cortex-M3 (SiLabs) SOC. I need to move the interrupt vector [edit] and the code away from the flash memory to make room for the โ€œbootloaderโ€. The bootloader starts at address 0 to exit when the kernel exits reset. Its function is to check the main image loaded with a higher address and possibly replace this main image with a new one.

Therefore, the loader will have its own vector table at 0, and then its code. At a higher fixed address, say 8 KB, will be the main image, starting with its vector table.

I found this page that describes the vector table offset register that the loader can use (with masked interrupts, obviously) to point the hardware to the new vector table.

My question is how to connect the "main" image so that it works when writing to a flash, starting from scratch. I am not familiar with the ARM assembly, but I assume that the code is not position independent.

I am using the SiLabs Precision32 IDE, which uses gcc for the tool chain. I found how to add linker flags. My question is that the gcc gs flag will provide a change to the base of the vector table and code.

Thanks.

+4
source share
1 answer

vectors.s

.cpu cortex-m3 .thumb .word 0x20008000 /* stack top address */ .word _start /* Reset */ .word hang .word hang /* ... */ .thumb_func hang: b . .thumb_func .globl _start _start: bl notmain b hang 

notmain.c

 extern void fun ( unsigned int ); void notmain ( void ) { fun(7); } 

fun.c

 void fun ( unsigned int x ) { } 

Makefile

 hello.elf : vectors.s fun.c notmain.c memmap arm-none-eabi-as vectors.s -o vectors.o arm-none-eabi-gcc -Wall -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 -march=armv7-m -c notmain.c -o notmain.o arm-none-eabi-gcc -Wall -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 -march=armv7-m -c fun.c -o fun.o arm-none-eabi-ld -o hello.elf -T memmap vectors.o notmain.o fun.o arm-none-eabi-objdump -D hello.elf > hello.list arm-none-eabi-objcopy hello.elf -O binary hello.bin 

so if the linker script (memmap is the name I used) looks like this:

 MEMORY { rom : ORIGIN = 0x00000000, LENGTH = 0x40000 ram : ORIGIN = 0x20000000, LENGTH = 0x8000 } SECTIONS { .text : { *(.text*) } > rom .bss : { *(.bss*) } > ram } 

since all of the above is .text, no.bss and .data, the linker takes the objects listed on the ld command line and places them starting at that address ...

mbly of the .text section:

 00000000 <hang-0x10>: 0: 20008000 andcs r8, r0, r0 4: 00000013 andeq r0, r0, r3, lsl r0 8: 00000011 andeq r0, r0, r1, lsl r0 c: 00000011 andeq r0, r0, r1, lsl r0 00000010 <hang>: 10: e7fe bn 10 <hang> 00000012 <_start>: 12: f000 f801 bl 18 <notmain> 16: e7fb bn 10 <hang> 00000018 <notmain>: 18: 2007 movs r0, #7 1a: f000 b801 bw 20 <fun> 1e: bf00 nop 00000020 <fun>: 20: 4770 bx lr 22: bf00 nop 

So, for this you need to be careful to put your bootstrap code on the command line first. But you can also do such things with a linker script.

order matters by listing specific object files and then the generic .text later

 MEMORY { romx : ORIGIN = 0x00000000, LENGTH = 0x1000 romy : ORIGIN = 0x00010000, LENGTH = 0x1000 ram : ORIGIN = 0x00030000, LENGTH = 0x1000 bob : ORIGIN = 0x00040000, LENGTH = 0x1000 ted : ORIGIN = 0x00050000, LENGTH = 0x1000 } SECTIONS { abc : { vectors.o } > romx def : { fun.o } > ted .text : { *(.text*) } > romy .bss : { *(.bss*) } > ram } 

and get it

 00000000 <hang-0x10>: 0: 20008000 andcs r8, r0, r0 4: 00000013 andeq r0, r0, r3, lsl r0 8: 00000011 andeq r0, r0, r1, lsl r0 c: 00000011 andeq r0, r0, r1, lsl r0 00000010 <hang>: 10: e7fe bn 10 <hang> 00000012 <_start>: 12: f00f fff5 bl 10000 <notmain> 16: e7fb bn 10 <hang> Disassembly of section def: 00050000 <fun>: 50000: 4770 bx lr 50002: bf00 nop Disassembly of section .text: 00010000 <notmain>: 10000: 2007 movs r0, #7 10002: f03f bffd bw 50000 <fun> 10006: bf00 nop 

short answer with gnu tools you use the script linker to manipulate where it all ended, I assume you want these functions to be in the role in a specific place. I do not quite understand what you are doing. But if, for example, you try to put something simple, like a branch in main () in a flash, initially with main () being deeper in the flash, then somehow or through some code it will be deeper in the flash , or in some other way, then later you only delete and reprogram items that are close to zero. you still need a simple branch for main () for the first time. you can force what I call vectors.o to be at the zero address, then .text can be deeper into the flash, putting all the reset code in the main there, then leave it in flash and replace only the material with zero.

like this

 MEMORY { romx : ORIGIN = 0x00000000, LENGTH = 0x1000 romy : ORIGIN = 0x00010000, LENGTH = 0x1000 ram : ORIGIN = 0x00030000, LENGTH = 0x1000 bob : ORIGIN = 0x00040000, LENGTH = 0x1000 ted : ORIGIN = 0x00050000, LENGTH = 0x1000 } SECTIONS { abc : { vectors.o } > romx .text : { *(.text*) } > romy .bss : { *(.bss*) } > ram } 

gives

 00000000 <hang-0x10>: 0: 20008000 andcs r8, r0, r0 4: 00000013 andeq r0, r0, r3, lsl r0 8: 00000011 andeq r0, r0, r1, lsl r0 c: 00000011 andeq r0, r0, r1, lsl r0 00000010 <hang>: 10: e7fe bn 10 <hang> 00000012 <_start>: 12: f00f fff7 bl 10004 <notmain> 16: e7fb bn 10 <hang> Disassembly of section .text: 00010000 <fun>: 10000: 4770 bx lr 10002: bf00 nop 00010004 <notmain>: 10004: 2007 movs r0, #7 10006: f7ff bffb bw 10000 <fun> 1000a: bf00 nop 

then leave things 0x10000 and replace material 0x00000 later.

Anyway, the short answer is a script linker, you need to create a script linker to put things where you want. The gnu linker scripts can become extremely complex, I tend to be simple.

If you want to place everything at a different address, including your vector table, then something like this is possible:

hop.s

 .cpu cortex-m3 .thumb .word 0x20008000 /* stack top address */ .word _start /* Reset */ .word hang .word hang /* ... */ .thumb_func hang: b . .thumb_func ldr r0,=_start bx r0 

and this one

 MEMORY { romx : ORIGIN = 0x00000000, LENGTH = 0x1000 romy : ORIGIN = 0x00010000, LENGTH = 0x1000 ram : ORIGIN = 0x00030000, LENGTH = 0x1000 bob : ORIGIN = 0x00040000, LENGTH = 0x1000 ted : ORIGIN = 0x00050000, LENGTH = 0x1000 } SECTIONS { abc : { hop.o } > romx .text : { *(.text*) } > romy .bss : { *(.bss*) } > ram } 

gives it

 Disassembly of section abc: 00000000 <hang-0x10>: 0: 20008000 andcs r8, r0, r0 4: 00010013 andeq r0, r1, r3, lsl r0 8: 00000011 andeq r0, r0, r1, lsl r0 c: 00000011 andeq r0, r0, r1, lsl r0 00000010 <hang>: 10: e7fe bn 10 <hang> 12: 4801 ldr r0, [pc, #4] ; (18 <hang+0x8>) 14: 4700 bx r0 16: 00130000 1a: 20410001 Disassembly of section .text: 00010000 <hang-0x10>: 10000: 20008000 andcs r8, r0, r0 10004: 00010013 andeq r0, r1, r3, lsl r0 10008: 00010011 andeq r0, r1, r1, lsl r0 1000c: 00010011 andeq r0, r1, r1, lsl r0 00010010 <hang>: 10010: e7fe bn 10010 <hang> 00010012 <_start>: 10012: f000 f803 bl 1001c <notmain> 10016: e7fb bn 10010 <hang> 00010018 <fun>: 10018: 4770 bx lr 1001a: bf00 nop 0001001c <notmain>: 1001c: 2007 movs r0, #7 1001e: f7ff bffb bw 10018 <fun> 10022: bf00 nop 

then you can change the vector table to 0x10000, for example.

if you ask another question, for example, as a loader on 0x00000, then the loader modifies the flash to add the application, say, to 0x20000, then you want to run this application, there are simpler solutions that do not necessarily require changing the location of the vector table.

+6
source

Source: https://habr.com/ru/post/1496270/


All Articles