2023-09-09 09:07 PM
I am testing doing flash erase while running code from internal SRAM on a STM32F072B Discovery Board. Having initializing everything with code running in flash, I call a function where itself and all its dependencies exist in RAM. I've verified this in many ways: code analysis, stepping through debugger, etc. I have also copied the ISR vectors to RAM at 0x2000_0000 and used SYSCFG_CFGR1 register to remap SRAM to 0x0000_0000.
I have TIM2_CH1 setup as a 100kHz timer and increment a tick variable each interrupt. The interrupt also toggles a GPIO pin every pulse. Currently that is connected to an LED so I can visualize what's going on, but I have tested with a bare pin at GPIO_SPEED_FREQ_HIGH as well with the same results.
All of this works fine as long as I don't do the flash erase cycle. But as soon as I erase a few pages of flash, the LED starts flickering quite a bit like the GPIO bus is being blocked. The datasheet says that flash should only block the flash bus; running in SRAM is supposed to avoid CPU stalls. The GPIO also doesn't seem to be on the same bus. So my question is why is this happening? I have attached some logic analyzer captures of the GPIO. In the macro view you can see two white blocks on the left and right ends. This is the 100kHz signal. Once the signal becomes sparse that is when flash erase is in progress. The toggling is extremely slow and erratic during this time frame. I also attached a close up on the 200kHz signal to show that it is functioning fine outside of the flash erase cycle.
I've also attached the project which is based off one of the examples in the SDK. I copied many functions into My_XXX variants to place them into RAM.
Solved! Go to Solution.
2023-12-01 10:55 PM
Well it took almost 3 months but finally figured out the problem. Was working with ST tech support off and on during that time. This week after messing around with loading the entire project into SRAM the error went away. Found that there was something being accessed from flash in the timer interrupt that I had failed to find previously. The code has changed a lot so I'm not sure if that was even the original problem, but it is working now with a mix of flash and SRAM based code.
2023-09-09 09:11 PM
I forgot to mention one thing. I also timed the flash erase cycle using the TIM2_CH1 timer (through the tick2 variable). This showed around 106k ticks, which coincides with the wall clock I timed it at about 1.06s. So it seems like the timer is running fine; it's only the GPIO that is being blocked but it's not stalling the CPU.
2023-09-10 12:14 AM
What LA do you use? What's its decision level, can it be changed? It would be better to observe the pin using an oscilloscope, can you try?
JW
2023-09-10 02:20 PM
I'm not sure what you mean by decision level. I'm using a DSLogic Plus. If you mean the voltage threshold level it's currently set to 1V though I can set it lower.
But I ran it today on the oscilloscope. Looks more or less the same. Don't see any obvious signal integrity issues. There is some bad ringing but I think that's just my probing technique. I've attacked some screencaps showing the full flash cycle and zooms with smaller horz scale with cursors including a closeup of the "glitch." I'm not really sure what's causing that.
2023-09-10 03:09 PM - edited 2023-09-10 03:13 PM
Where/how are LEDs defined?
Is SB16 closed?
Try toggle a different pin, perhaps not in VDDIO2 domain. Try to toggle it in the loop waiting for FLASH programming finished.
JW
2023-09-10 06:20 PM
I checked that SB16 is closed; it has a zero ohm resistor across it (checked with DMM). II have also added a new toggle on PB15 (not on VDDIO2 domain) that toggles after each instruction in the My_PageErase function as shown below:
static void NOINLINE FLASHAPI My_PageErase(uint32_t PageAddress)
{
/* Proceed to erase the page */
My_GPIO_TogglePin(GPIOB, GPIO_PIN_15);
SET_BIT(FLASH->CR, FLASH_CR_PER);
My_GPIO_TogglePin(GPIOB, GPIO_PIN_15);
WRITE_REG(FLASH->AR, PageAddress);
My_GPIO_TogglePin(GPIOB, GPIO_PIN_15);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
}
I've switched back to using the LA because it's simpler to capture. Let me know if you want oscope. Channel 0 is now the PB15 signal and Channel 2 is the LED. This is what the above code produces:
I tried adding the toggle also to the WaitForFlashComplete function inside of the loop and that produces this:
2023-09-11 02:46 AM
Most intriguing, yet I have no explanation. As if the AHB2 bus (dedicated to GPIO in 'F0) would be stalled during FLASH programming, yet would not throw wait to the processor.
I believe, only ST can explain this, so you may want to contact them, probably through the web support form.
JW
PS. Meantime, as an experiment, you could try to toggle a pin not through GPIO, but through TIM channel set to output compare, but not PWM, but toggle between Force Inactive and Force Active in TIMx_CCMRx.OCxM.
2023-09-11 11:06 PM
Thanks for the help. I will reach out to ST.
I tried your experiment. First I setup TIM2_CH1 as regular compare output and saw that the expected 50kHz was appearing on the pin during the flash erase cycles. I then switched to using force output and see the exact same behavior as when trying to toggle the GPIO directly. Quite strange.
2023-12-01 10:55 PM
Well it took almost 3 months but finally figured out the problem. Was working with ST tech support off and on during that time. This week after messing around with loading the entire project into SRAM the error went away. Found that there was something being accessed from flash in the timer interrupt that I had failed to find previously. The code has changed a lot so I'm not sure if that was even the original problem, but it is working now with a mix of flash and SRAM based code.
2023-12-02 01:20 AM - edited 2023-12-02 01:21 AM
I can't accept this as a solution.
The original problem was described so, that GPIO with LED toggled in timer ISR does not toggle during programming, but the tick2 variable incremented in the very same ISR does increment. This is the ISR from code you've posted in opening post (btw. you should be able to reproduce the original problem using that code):
void RAMFUNC TIM2_IRQHandler(void)
{
TIM2->SR &= ~TIM_SR_UIF;
tick2++;
My_LED_Toggle(LED4);
}
And this is what you've said:
I also timed the flash erase cycle using the TIM2_CH1 timer (through the tick2 variable). This showed around 106k ticks, which coincides with the wall clock I timed it at about 1.06s. So it seems like the timer is running fine; it's only the GPIO that is being blocked but it's not stalling the CPU.
Reading FLASH during programming would stall execution, thus tick2 would not get incremented.
Can you please poke your ST's contact once more, pointing them to this post?
JW