[STM32] Interrupts in cmodules do not preempt the main loop #12828
-
I wrote a cmodules code with stm32f405rgt6 and compiled it successfully. The function of this cmodules code is to switch the level state of GPIO regularly. The following is the timer initialization code
After successfully programming the compiled firmware, I successfully saw the GPIO switching. But when I wrote other code in the micropython main loop, I found that the GPIO switching was different. It felt like the timer interrupt did not preempt the main loop. Whether the interrupt in micropython cannot be preempted? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 18 replies
-
If you're using the timer in PWM mode to directly drive the pin, you can do this directly in micropython without using C for timer config
If you are only flipping a pin from the timers you should use the directly managed timer channel because then there's no interrupt actually involved, it's all in hardware. Or are you firing off a Timer interrupt that runs other code, not just pin on/off ? There is a heirachy to the interrupts, ones with a lower number can / do pre-empt lower number ones in progress: Line 134 in 64c79a5 So it will depend on what code is running in main whether it's doing something that can preempt timer interrupts - looking at that list the obvious one is probably flash.... or lots of uart / usb traffic ? Considering you're already coding in C land, you can change the IRQ prio on the timer interrupt enable commands, but keep in mind that you might cause issues in the other interrupts if your timer one runs too long. Also if you're writing to internal flash, that completely blocks CPU while in progress so all interrutps get paused. |
Beta Was this translation helpful? Give feedback.
-
I tried to reproduce this in pure python import pyb
pin = pyb.Pin("B12", pyb.Pin.OUT)
def cb(_):
pin.on()
pin.off()
tim = pyb.Timer(4)
tim.init(freq=25_000)
spi = pyb.SPI(1, pyb.SPI.CONTROLLER, baudrate=600000, polarity=1, phase=0)
b = "\xA5"*20000
def do_spi():
for _ in range(10): spi.write(b)
tim.callback(cb) On stm32F411, wIth python callback I couldn't get faster than ~35Khz timer before the interrupt was using 100% cpu. But with that code I had a pulse stream that when I ran the spi function I'd get some interruptions of ~80uS STATIC HAL_StatusTypeDef spi_wait_dma_finished(const spi_t *spi, uint32_t t_start, uint32_t timeout) {
volatile HAL_SPI_StateTypeDef *state = &spi->spi->State;
for (;;) {
if (*state == HAL_SPI_STATE_READY) {
return HAL_OK;
}
if (HAL_GetTick() - t_start >= timeout) {
return HAL_TIMEOUT;
}
}
return HAL_OK;
} But the same 80uS interruptions occurred, no change at all. So I'm not sure where the issue is; perhaps it's an irq priority issue on my end, but even then I'm not seeing the 200uS interruptions you're getting. |
Beta Was this translation helpful? Give feedback.
That's curious, I'm not really sure why it's needing to disable interrupts like that.... however I'd expect the wfi / re-enable should really kick in for the timer interrupt as well anyway and work without any particular delay to timer interrupt.
It'd be worth a test with the irq disable/enable lines commented out to just see what happens.