cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 custom Bootloader with external/seperate main app code and ISRs - two seperate programs as per examples but do not deal with ISRs

MEdgerton
Senior

I am using STM32CubeIDE and have used the linker to change settings, so have a pretty good grasp.

I have read on custom bootloaders but not found how they deal with the following issue, as it seems ignored in the demo code. The custom bootloaders shown by ST have two programs. The bootloader/programmer and then the main code.

For example the lwip http or tftp prgrammer with seperate application code:

https://www.st.com/resource/en/user_manual/dm00103145-stm32cube-ethernet-iap-example-stmicroelectronics.pdf

I am writing a bootloader to perform a startup check and possible firmware update of the main code which will be in external FLASH.

How do you make this deal with ISRs and the fixed vectors?

As I understand as is normal, the interupt vectors are fixed. So when the bootloader runs, the vectors will be used there.

But if I then jump into the main code then the ISR vectors will be to the bootloader code. That isn't any good.

How do I overcome this? Do I have to make a map in the bootloader that the main code somehow gets called?

Or should the bootloader just not have any ISRs and they are all directed to the main code - the issue being if there is a fw update of the main code going on and something fails which normally code be dealt with, it will instead jump to code that may not have been programmed.

The same question goes for if you were to run all the code in SRAM/external SDRAM ?

Are the vectors loaded into a volatile store as to where they point so you can change the point they jump to? Or always jumpt to fixed flash locations?

I.e. Does changing this change my interupt vector table so I can point it elsewhere?

/* The startup code goes first into RAM_EXEC */

 .isr_vector :

 {

  . = ALIGN(4);

  KEEP(*(.isr_vector)) /* Startup code */

  . = ALIGN(4);

 } >RAM_EXEC

This is also stored in the FLASH, So I assume this is stored in the FLASH then automatically loaded to the RAM_EXEC which defines the actual call vectors, so changing the RAM table will change the vectors ?

I look forward to your replies on this, it must have come up but I havent seen any articles on it, despite there being good examples of writing two seperate programs do cover this very topic.

Thanks,

Mark

4 REPLIES 4

Which part? All except the CM0 provide for the address of the vector table to be set into SCB->VTOR this is usually done in SystemInit(), ST uses defines, but one could as easily use symbols the linker binds. The table needs to be aligned, depending on overall size/capacity, usually a 512 byte boundary for most STM32

The vector table could be mapped into RAM, from there the individual vectors could be changed on the fly.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
MEdgerton
Senior

Thanks @Community member​ I am using the STM32H743zi2.

Have you an example of the symbol method?

Also does this then mean when mean if the bootloader I write then jumps to the main app which has its own SystemInit() then the tables will get updated appropriately? - assuming they are correctly set in the linker for places in the external Flash (or SDRAM).

void SystemInit(void)
{
 ...
  extern void *__Vectors; // Keil, for GNU g_pfnVectors
  SCB->VTOR = (uint32_t)&__Vectors; /* Vector Table Relocation */
}

For SDRAM you have some chicken/egg issues. Typically SystemInit() should bring up your external interfaces, ie QSPI, SDRAM, etc, and then subsequently code in startup.s should unpack the statics into your RAM(s) from content in FLASH (Internal, QSPI, etc)

Contractually you could move all the Clock, PLL, and external memory initialization into the Loader, do it once, cleanly there, and then not have the Application touch the physical configuration, so basically run with the clocks and memory the loader has instantiated.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thanks. That is very useful to know as it saves de-initiallaising.

I was going to test to see if I could keep the LwIP stack going between the two, or at least hold the IP address. The make the client side pull data to refresh the page from a known new one if it jumps to the bootloader to do a fw update. In theory it should work, but I do realise it is risky.

My plan was just to ensure the device stays at the same IP address, and start the stack in the other code again but giving it the IP if it already has one. The the client side code can pull and all should be well.

In theory as it will have the same MAC (or can be set to) even a DHCP request the lease should still be valid and get the same IP, but not all routers are created equal!

The worst case is that the web callback cannot find the device and just has to handle it properly. Meanwhile the LwIP stack can go to a default IP like many devices do.