cancel
Showing results for 
Search instead for 
Did you mean: 

BFB2 with exception vector stack in CCM SRAM

Hello,

I'm trying to use the BFB2 feature on the STM32G474CET microcontroller. I'm able to flash binaries into each of the two banks, and so long as the stack pointer defined in the first word of the interrupt table points to an SRAM location (0x20000000-based) my Bank 2 code will execute if I set the BFB2 bit.

However, we want to locate our stack/variables/heap all in CCM SRAM (0x10000000-based). If I store a CCM location (specifically, 0x100008F0) in the first word of the Bank 2 interrupt table and then set BFB2, instead of executing my Bank 2 code the MCU spins forever in the bootloader. Note that in this case it doesn't even try to execute the valid Bank 1 code even though AN2606 kind of implies that it would move on to the other bank if the Bank 2 stack address isn't in SRAM. Finally, I also tried using the aliased CCM SRAM (0x20018000-based) and the bootloader code still failed to execute my code - it seems only SRAM1 (and maybe SRAM2 but I didn't try it) addresses work.

Are either of these limitations documented:

  1. Using BFB2 with the Bank 2 stack in CCM SRAM is not supported.
  2. Setting BFB2 with a Bank 2 CCM SRAM address will cause a bootloader hang and not failback to Bank 1 as described in AN2606.

?

Thanks,

TG

2 REPLIES 2

Actually, to answer my own point 2 above: the Bank 1 stack address was also in CCM SRAM, so maybe the bootloader is just spinning because it doesn't think the image in either bank is valid. I'd still like to know if CCM SRAM is even supposed to be supported for use as a stack in dual-bank mode.

I did find a workaround for this issue that relies on how the gcc startup scripts work (so probably isn't applicable to other compilers). The _mainCRTStartup/_start function will load the SP from the linker-script-defined __stack symbol. The way our interrupt table works is that we were populating the first entry with __stack and the second entry with the address of _mainCRTStartup (which would then redundantly go and populate SP with the value of __stack even though it was already set properly out of reset). Our workaround is to simply populate the interrupt table entry with a "valid" SP value in the SRAM1 range but keep __stack set to the CCM SRAM value that we actually want to use. Doing this allows both banks to work and _mainCRTStartup does the work to make sure our stack is where we want it before anything else is executed.

Obviously, this workaround is very specific to using gcc and populating the vector table with _mainCRTStartup as the reset handler entry point, but I thought I would share it in case it was helpful to others.