cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G0B1 jump across flash banks errata: what about interrupts?

berendi
Principal

There is this errata for STM32G0B1

2.2.10 Prefetch failure when branching across flash memory banks
Description
In rare cases, the code prefetch may fail upon branching and function calls across flash memory banks,
regardless of the DUAL_BANK and nSWAP_BANK option byte settings. The failing prefetch then provides an
incorrect data to the CPU, which causes code execution corruption and may lead to HardFault interrupt.

The workaround is obvious, either disable prefetch when jumping to code in the other bank and enable it again afterwards or use a small "trampoline" function in RAM. We can live with that, as our software is split into separately compiled "core" and "application" parts loaded into separate banks, having only a handful of interface functions there would be e.g. no jumps into library functions in the other bank.

 

What about exceptions and interrupts, how are they affected?

 

The ARM literature generally refers to loading the exception handler address from the vector table as fetching. It makes sense on architectures where there is a separate instruction and data bus, as it can stack a few registers while waiting for the address from the slower flash. This is not the case on Cortex-M0+, however there could still be an internal distinction between data loads and instuction fetches.

So, what happens when an exception occurs while code is running in bank 1 and NVIC->VTOR points to bank 0?

What happens when an interrupt handler running in bank 0 returns to code in bank 1?

Are those kinds of branches affected by this errata or only literal BX,BLX and BL instructions? All of them?

Having the vector table and a small handler function in RAM would solve that problem, right?

Oh, and to complicate matters further there is a RTOS (ThreadX) running in bank 0 that might want to return to a different address and mess with the stack.

10 REPLIES 10

@Bubbles wrote:

The problem appears when the flash is already prefetching and the execution branches to the other bank. There's a signal missing to invalidate the prefetch buffer in this particular case and it will present the previous prefetch instructions twice. It's very sensitive to code alignment. There are 4 possible positions of the 16-bit branch instruction within the flash word and only one fails. I did not investigate the 32b BL instruction, I assume it would be similar.


Hmm, gcc does have a way to align all branch targets (e.g. -falign-labels=4), but I don't think it has a way to align all branches... though it may be pretty easy to wrap the assembler in a script that preprocesses the assembly to insert an alignment directive before every branch before passing it on to the real assembler. It would no doubt have much less performance overhead than disabling prefetch entirely.

... vector table and interrupt handlers (or at least small wrappers that toggle prefetch on entry and exit) would still have to be in SRAM though