-
Notifications
You must be signed in to change notification settings - Fork 8k
Description
Describe the bug
I'm using DMA with OSPI on a STM32U5A5, and keep getting transfer errors. The log output seems to suggest that the callback is somehow called before the transfer complete flag is set.
The same setup works fine without DMA configured, and happens less frequently at lower frequencies.
Regression
- This is a regression.
Steps to reproduce
Build with the dmas
and dma-names
properties commented out, things work fine.
Build with them uncommented, and the log is spammed with transfer errors.
Lower the ospi-max-frequency
(for example all the way down to 5M) and the errors only occur sporadically.
Relevant log output
[00:00:08.350,000] <err> dma_stm32: Transfer Error.
[00:00:08.350,000] <inf> dma_stm32: tc: 0, ht: 0, dte: 0, ule: 0, use: 0
[00:00:08.350,000] <err> flash_stm32_ospi: DMA callback error with channel 12.
[00:00:08.374,000] <err> dma_stm32: Transfer Error.
[00:00:08.374,000] <inf> dma_stm32: tc: 0, ht: 0, dte: 0, ule: 0, use: 0
[00:00:08.374,000] <err> flash_stm32_ospi: DMA callback error with channel 12.
Impact
Functional Limitation – Some features not working as expected, but system usable.
Environment
No response
Additional Context
Using the following DTS:
&octospi1 {
pinctrl-0 = <&octospim_p1_clk_pf10 &octospim_p1_ncs_pa2
&octospim_p1_io0_pf8 &octospim_p1_io1_pf9
&octospim_p1_io2_pf7 &octospim_p1_io3_pf6>;
pinctrl-names = "default";
dmas = <&gpdma1 12 40 0>; /* OCTOSPI request ID = 40, flags not used */
dma-names = "tx_rx";
status = "okay";
mx25l25645g: ospi-nor-flash@0 {
compatible = "st,stm32-ospi-nor";
reg = <0 DT_SIZE_M(32)>;
ospi-max-frequency = <DT_FREQ_M(50)>;
/* WP# and RESET# pin used for data lines in QUAD mode,
* reset-gpios cannot be used in combination.
*/
spi-bus-width = <OSPI_QUAD_MODE>;
status = "okay";
/* Supports DTR (double transfer rate)
* Flash driver only allows DTR with OPI mode (8 line mode).
*/
data-rate = <OSPI_STR_TRANSFER>;
four-byte-opcodes;
};
};
A coworker suggested he has seen a similar issue on another STM32, where the ISR somehow got called before the flags were set. Adding a small patch to poll the flags a few times before giving up seems to cause the problem to go away:
diff --git a/drivers/dma/dma_stm32u5.c b/drivers/dma/dma_stm32u5.c
index 88ab979df62..76445ac59a7 100644
--- a/drivers/dma/dma_stm32u5.c
+++ b/drivers/dma/dma_stm32u5.c
@@ -265,6 +265,12 @@ static void dma_stm32_irq_handler(const struct device *dev, uint32_t id)
}
callback_arg = id + STM32_DMA_STREAM_OFFSET;
stream->busy = false;
+ for(int i = 0; i < 100; i++) {
+ if (!(stm32_dma_is_tc_irq_active(dma, id) | stm32_dma_is_ht_irq_active(dma, id))) {
+ // check the flags a few times, because sometimes the interrupt comes early
+ // for some reason
+ }
+ }
/* The dma stream id is in range from STM32_DMA_STREAM_OFFSET..<dma-requests> */
if (stm32_dma_is_ht_irq_active(dma, id)) {