cancel
Showing results for 
Search instead for 
Did you mean: 

How to write external flash while the code is executing in the same external flash (QSPI configured in memory map mode)?

Luca G.
Associate III

Dear all,

I need to write the external flash while the code is executing in the same external flash (QSPI configured in memory map mode).

I know that in this mode it's only possible (obviously) to read the flash but I need to update firmware.

To do this I can implement one bootloader in internal flash but if it's possible I want to implement the writing operations in the application (therefore in external flash).

I'm thinking to implement the functions to erase and write the external flash in a fixed position of internal flash memory (with linker script) and call this function in external flash when I want to write the external flash.

Inside these functions I switch in indirect mode using the erase or wirite HAL functions and, before to return from function, activate again the memory map mode.

1° question: this idea could works fine?

2° question: for call the functions in internal from external flash, can I use the same code that I use to jump from internal to external flash (like this: https://community.st.com/s/question/0D50X00009Xkdol/stm32l4-bootloader-on-internal-flash-jumping-to-application-on-external-flash)?

Thanks in advance.

Luca G

5 REPLIES 5

In my experience you can't do the two concurrently. And the write/erase is very slow, so would likely be a drag on real-time execution.

You can run code from RAM.

You can make a mixed mode image, with a portion that runs in Internal flash, and the rest in external.

There are a number of ways to transfer control between different code segments. The real complication comes with the vector table, active interrupts, and making sure the call tree doesn't have any dependencies.

I might approach this by having an update loader in internal flash, and perhaps multiple application images in external flash.

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

Thank you for your replies!

@Community member​:

I implemented my solution but, when I jump to the code in internal flash, the processor go to the HardFault. I verified that the functions in internal flash is placed in correct address.

Is it the same code that usually have to use to jump from bootloader to application (for example)?

Can you suggest me some examples or link?

The solution you proposed me to execute the code in RAM is also interesting. I tried to implement it but when I tried to call the function in RAM from code in external flash, the processor does not go inside the function but the execution simply continues.

Can you suggest me example or application note for execute code in RAM?

@Andreas Bolsch​ 

Thanks but in my case I can't use two external flash.

It could be the same code.

The MCU just has to branch, could do with a function pointer. You can do the VTOR / SP stuff at the front of the Reset_Handler so these things occur automatically rather than labour through them at the control transfer point, where changing the stack might be riskier. There is no expectation of returning from the Reset_Handler. Remember the address of Thumb functions are ODD (A0=1) if this is not done the MCU will Hard Fault.

Could be a stack, interrupt, or host of other regions. Watch for initializing clocks, interfaces, etc. Usually decide which component is responsible and do it once.

I don't story-board these things because it takes longer than just implementing them.

I have functional Hard Fault routines in the loaders/apps so I can decompose the failure with useful/actionable data. Also do this on the Error_Handler() paths, ideally with __FILE__ and __LINE__ data so you can track it down quickly. Remember the CM4 will also Hard Fault on uninitialized memory decode regions, ie you touch QSPI memory prior to initialization, or reset/reinit of the QSPI peripheral.

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

Dear clive1,

thanks for your reply and sorry for my delay.

I solved my problem and now I'm able to execute code in RAM by set properly the linker script file: I'm using "*(.ramcode)" inside ".data" region in linker script file, and "__attribute__ ((section(".ramcode")))" before every function that I want to execute in RAM.

Now seems works well.

The problem that when I execute code in debug and try to enter inside function that is in RAM, the debugger execute the function code but does not enter inside the function remains.

What could be the problem? Are there some settings in debug configuration for solve this problem?

Thanks in advance.