Hi,
It's about the STM32F103ZE uC and Keil uVision4.
As part of trying to deeply understand the Keil ARM tools I just like to 'fool' the linker to place code in a valid random flash memory location and have it executed after reset.
I can place code in a random location just by changing the Linker option R/O Base from the default value 0x8000 0000 to 0x8000 2000 which is in the valid memory range.
But having done this, when start debugging then the program counter starts on address 0xFFFF FFFE. So probably somehow the linker is missing a reset vector and therefore does not initialize the program counter.
(I managed to run this code by partly loading flash code and partly loading only the reset-vector separately)
How can I succeed in making the uC program counter point to the reset vector (address 0x8000 0004) when code is loaded at address 0x8000 2000 to execute this code. So after a reset I can change the vector-table offset in assembler in the reset-handler at 0x8000 0004 and then jump to the reset-vector at address 0x0800 2004?
Or do I need to use/modify some scatter file for this operation?
Hope to hear from the experts... ;-)
Thanks,
Henk
Henk,
I only worked a little bit with a LPC1768 so I am far from being an authority on it. In order to remap the vector table before jumping to another program, you can
NVIC_SetVectorTable(NVIC_VectTab_FLASH, MAIN_BOOT_FLASH_START);
where
void NVIC_SetVectorTable(DWORD NVIC_VectTab, DWORD Offset) { NVIC_VECT_TABLE = NVIC_VectTab | (Offset & 0x1FFFFF80); }
Assuming your bootloader is jumping to an application which is located at 0x1000, the actual jump with be performed like this:
__asm void jump_to_application(void) { ; program stack pointer of the application LDR R0, =0x1000 ;=APPLICATION_START LDR SP, [R0] ; extract entry point of the application LDR R0, =0x1004 ;=APPLICATION_START+4 ; jump LDR PC, [R0] }
I was aware of the fact that the vector-table offset can be modified by code. But I was searching for an option to only have the reset vector located on it's original address 0004 and have the remaining vectors and vector handlers and all other code positioned at address 2000 or elsewhere.
I studied the linker options but did not find anything in that direction.
Then I studied and experimented with the scatter file stuff which was unknown to me for about 10 hours. I managed to get my application running using the scatter file.
As far as I understand: by default the compiler and assembler both generate all kinds of blocks with related code or with related data called 'Regions'. The linker combines these Regions to executable code with help of a few linker settings like the base addresses of Flash and Ram.
Another way to control the Linker is to use a Scatter file. A scatter file is a simple ASCII file to be constructed by the user. In this scatter file all Regions can be assigned on which address they will be stored. It helped me a lot to look in the map file for understanding Region names and functions. Still not all is clear to me.
The reset-vector is part of the vector-table. The vector-table contains the initial stack pointer value, the reset-vector and all other interrupt vectors. The reset-vector can not be separated from the vector-table. The vector-table is not allowed to be positioned on any other location than 0000.
But I managed to use all kind of different code and ram locations to position different Regions of my application and it runs correctly. It uses a USART interrupt to show data in Hyperterminal and this works fine so the vector table is working as it should.
When using only a scatter file in the Linker the Linker does not generate a vector-table.
As soon as a scatter file is selected in the linker, the linker removes the default linker command line options.
I did not find any option to define the vector-table in the scatter file. So I just copied (by guess) the default command line option '--first __Vectors' in the Linker 'Misc controls' textbox. The linker now generates a warning but low and behold the Linker generates the vector-table and my application runs fine.
Thanks for listening,
hopefully other newbies like me are helped by this info...;-)