Hi there,
I'm working on a bootloader that uses a hex file.
What does this row do?
:0400000508000131BD
It breaks up to these:
: Start code 04 Byte count: 4 0000 Address 05 Record type: Start Linear Address Record 08000131 <--- is this a start address? BD Checksum
Does it say the execution start (IP) address is 0x08000131? My main program range is from 0x08000000 to 0x0800261. Or should I discard the line altogether?
Thanks. -Mad D
Now that we have the map file, it's easier to see what's going on. I can see where 0x08000000 comes from: this is an STM32F10x device.
As you can see, the first 0x130 bytes are the RESET section. I'm not sure what this part is really doing...
The RESET section contains interrupt and exception vectors.
I am in the design phase, so Im trying to understand how the start address is handled in the hex file.
If I were to design a bootloader, I would ignore the start address record in the HEX file. The natural thing for the bootloader to do when passing control to main application is to emulate the CPU out of reset: the Cortex-M3 CPU will initialize the stack pointer with the value from location 0, then jump to address stored at location 4 (see Cortex-M3 manual for details.) Perhaps, you can get away with simply resetting the CPU and letting it run your main application.
Hi Mike,
Thanks for the reply.
To put things into perspective, 0x08000000 - 0x0800012C is taken up by the "Table 61. Vector table for other STM32F10xxx devices" as stated in the manual.
When we allocate 4 bytes for the last vector, 0x08000130 is the starting address. Do you know why the entry point is 0x08000131?
-Mad D
Do you know why the entry point is 0x08000131?
I think I do. 0x08000130 is the start address. By the way, it is possible to rewrite the scatter file in such a way that the start address is different. Then 1 is added to the address to indicate processor state (Thumb, as opposed to ARM) at program start. This (odd) address can be used with the BX instruction to jump to program start and switch processor state automatically. This isn't of much use for the Cortex-M3 since it can only be in Thumb state. It would be different if the CPU was, say, ARM7TDMI (supports both ARM and Thumb instructions.)
Program starting from 0x08000000:
Memory Map of the image Image Entry point : 0x08010131 Load Region LR_IROM1 (Base: 0x08010000, Size: 0x00002618, Max: 0x00010000, ABSOLUTE) Execution Region ER_IROM1 (Base: 0x08010000, Size: 0x000024f4, Max: 0x00010000, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x08010000 0x00000130 Data RO 3056 RESET stm32f10x_vector.o 0x08010130 0x00000000 Code RO 3065 * .ARM.Collect$$$$00000000 entry.o(mc_w.l) 0x08010130 0x00000004 Code RO 3068 .ARM.Collect$$$$00000001 entry2.o(mc_w.l) 0x08010134 0x00000004 Code RO 3071 .ARM.Collect$$$$00000004 entry5.o(mc_w.l) 0x08010138 0x00000008 Code RO 3072 .ARM.Collect$$$$00000007 entry7.o(mc_w.l) 0x08010140 0x00000004 Code RO 3069 .ARM.Collect$$$$00002712 entry2.o(mc_w.l) 0x08010144 0x00000008 Code RO 3057 .text stm32f10x_vector.o 0x0801014c 0x00000024 Code RO 3073 .text init.o(mc_w.l)
Disassembly 0x08010128 039B LSLS r3,r3,#14 0x0801012A 0801 LSRS r1,r0,#0 0x0801012C 039D LSLS r5,r3,#14 0x0801012E 0801 LSRS r1,r0,#0 _main_stk: 0x08010130 F8DFD00C LDR.W sp,[pc,#12] ; @0x08010140 _main_scatterload: 0x08010134 F000F80A BL.W __scatterload_rt2 (0x0801014C) _main_init: 0x08010138 4800 LDR r0,[pc,#0] ; @0x0801013C 0x0801013A 4700 BX r0 0x0801013C 230D MOVS r3,#0x0D 0x0801013E 0801 LSRS r1,r0,#0 0x08010140 05D0 LSLS r0,r2,#23 0x08010142 2000 MOVS r0,#0x00 295: LDR R0, =__main 0x08010144 4800 LDR r0,[pc,#0] ; @0x08010148 296: BX R0 0x08010146 4700 BX r0 0x08010148 0131 LSLS r1,r6,#4 0x0801014A 0801 LSRS r1,r0,#0 __scatterload_rt2: 0x0801014C 4C06 LDR r4,[pc,#24] ; @0x08010168 0x0801014E 4D07 LDR r5,[pc,#28] ; @0x0801016C 0x08010150 E006 B 0x08010160 0x08010152 68E0 LDR r0,[r4,#0x0C] 0x08010154 F0400301 ORR r3,r0,#0x01 0x08010158 E8940007 LDM r4,{r0-r2} 0x0801015C 4798 BLX r3 0x0801015E 3410 ADDS r4,r4,#0x10 0x08010160 42AC CMP r4,r5 0x08010162 D3F6 BCC 0x08010152 0x08010164 F7FFFFE8 BL.W _main_init (0x08010138) 0x08010168 24D4 MOVS r4,#0xD4 0x0801016A 0801 LSRS r1,r0,#0 0x0801016C 24F4 MOVS r4,#0xF4 0x0801016E 0801 LSRS r1,r0,#0 383: {} 0x08010170 4770 BX lr 707: {}
Program starting from 0x08010000:
Memory Map of the image Image Entry point : 0x08000131 Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00002618, Max: 0x00020000, ABSOLUTE) Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x000024f4, Max: 0x00020000, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x08000000 0x00000130 Data RO 3056 RESET stm32f10x_vector.o 0x08000130 0x00000000 Code RO 3065 * .ARM.Collect$$$$00000000 entry.o(mc_w.l) 0x08000130 0x00000004 Code RO 3068 .ARM.Collect$$$$00000001 entry2.o(mc_w.l) 0x08000134 0x00000004 Code RO 3071 .ARM.Collect$$$$00000004 entry5.o(mc_w.l) 0x08000138 0x00000008 Code RO 3072 .ARM.Collect$$$$00000007 entry7.o(mc_w.l) 0x08000140 0x00000004 Code RO 3069 .ARM.Collect$$$$00002712 entry2.o(mc_w.l) 0x08000144 0x00000008 Code RO 3057 .text stm32f10x_vector.o 0x0800014c 0x00000024 Code RO 3073 .text init.o(mc_w.l)
Disassembly 0x08000128 039B LSLS r3,r3,#14 0x0800012A 0800 LSRS r0,r0,#0 0x0800012C 039D LSLS r5,r3,#14 0x0800012E 0800 LSRS r0,r0,#0 _main_stk: 0x08000130 F8DFD00C LDR.W sp,[pc,#12] ; @0x08000140 _main_scatterload: 0x08000134 F000F80A BL.W __scatterload_rt2 (0x0800014C) _main_init: 0x08000138 4800 LDR r0,[pc,#0] ; @0x0800013C 0x0800013A 4700 BX r0 0x0800013C 230D MOVS r3,#0x0D 0x0800013E 0800 LSRS r0,r0,#0 0x08000140 05D0 LSLS r0,r2,#23 0x08000142 2000 MOVS r0,#0x00 295: LDR R0, =__main 0x08000144 4800 LDR r0,[pc,#0] ; @0x08000148 296: BX R0 0x08000146 4700 BX r0 0x08000148 0131 LSLS r1,r6,#4 0x0800014A 0800 LSRS r0,r0,#0 __scatterload_rt2: 0x0800014C 4C06 LDR r4,[pc,#24] ; @0x08000168 0x0800014E 4D07 LDR r5,[pc,#28] ; @0x0800016C 0x08000150 E006 B 0x08000160 0x08000152 68E0 LDR r0,[r4,#0x0C] 0x08000154 F0400301 ORR r3,r0,#0x01 0x08000158 E8940007 LDM r4,{r0-r2} 0x0800015C 4798 BLX r3 0x0800015E 3410 ADDS r4,r4,#0x10 0x08000160 42AC CMP r4,r5 0x08000162 D3F6 BCC 0x08000152 0x08000164 F7FFFFE8 BL.W _main_init (0x08000138) 0x08000168 24D4 MOVS r4,#0xD4 0x0800016A 0800 LSRS r0,r0,#0 0x0800016C 24F4 MOVS r4,#0xF4 0x0800016E 0800 LSRS r0,r0,#0 383: {} 0x08000170 4770 BX lr 707: {} 0x08000172 4770 BX lr
The explanation about the byte made sense, but I can't make sense of it when I check the map and the disassembly.
I changed the start locations to check whether thats what you meant... What I am thinking is to have the bootloader in the lower address and then jump to the program in the :0400000508010131BC record. What do you think?
PS: Sorry I flipped the "Program starting from 0x080X0000:"! But you understand :-P
I changed the start locations to check whether thats what you meant...
What I really meant is that the starting address doesn't necessarily follow the vector table. It is possible to reorder sections more or less arbitrarily, so the starting address may end up in the middle of the firmware code. But that doesn't have anything to do with bootloader.
What I am thinking is to have the bootloader in the lower address and then jump to the program in the :0400000508010131BC record. What do you think?
That makes sense. Don't forget to adjust the vector table offset register of the NVIC in your main application since the vector table will not be at its usual location. Still, I think it's better not to rely on the start address record in the HEX file. The start address record can be lost if you convert the HEX file (say, hex->bin->hex, or whatever.) Fetch the starting address from 0x08010004 and use it instead.
Hello Mike,
Thank you for the very informative replies. I found what you were talking about earlier, I'm just going to post it in case someone else reads this.
Quoted from the manual: After this startup delay has elapsed, the CPU fetches the top-of-stack value from address 0x0000 0000, then starts code execution from the boot memory starting from 0x0000 0004. ...the Flash memory contents can be accessed starting from address 0x0000 0000 or 0x800 0000.
0x00000000 05D0 LSLS r0,r2,#23 0x00000002 2000 MOVS r0,#0x00 0x00000004 0145 LSLS r5,r0,#5 0x00000006 0800 LSRS r0,r0,#0
0x08000000 05D0 LSLS r0,r2,#23 0x08000002 2000 MOVS r0,#0x00 0x08000004 0145 LSLS r5,r0,#5 0x08000006 0800 LSRS r0,r0,#0
Vector table for other STM32F10xxx devices
Description - Reserved Position - Priority - Type of priority - Acronym - Address - 0x0000_0000
Description - Reset Position - Priority - -3 Type of priority - Fixed Acronym - Reset Address - 0x0000_0004
Sorry, I had to break it into two posts...
I can see that the top-of-stack address is 0x200005D0 in the SRAM and the start address is 0x08000145, which is different from 0x08000131. Any idea why?
I have set the stack to 0x400 and heap to 0x400. Why is the top-of-stack 0x5D0?
Cheers.
The answer to both questions is "Why not?" Apparently, you have some expectations as to the resulting firmware image layout and the linker is not meeting your expectations. I have no idea where those expectations came from. They should come from the manual. You should familiarize yourself with the linking process. Read up on sections, regions, scatter files, etc:
http://www.keil.com/support/man/docs/armlink/