F4 DMA2 errata - how to handle that
Hello!
We have choosen the STM32F407/427 for our product, a couple of years ago.
It fits with the speed, and also with the possibility to use DMA for mutliple peripherals.
Now, as we have found out the hard way, the DMA2 fails while handling ADCs and SDIO.
As of now, I have found the F4 errata, and also the great writeup at https://blog.frankvh.com/2012/01/13/stm32f2xx-stm32f4xx-dma-maximum-transactions/ .
Obviously, this does happen quite randomly, and we got to it just after debugging a set of field returns. During the development and testing, it might have had occured, but it was obviously missed (SDIO failures granted that the card was weared down, etc.).
Anyway, the product is out, and I need to find a working FW changes to update it,
and to remove the major DMA issue.
I have searched the forum, but not much useful has been found.
To describe the situation:
on DMA2, there is
- ADC1 - Stream4 CH0 , ADC digitizing three channels, one time before DMA Stream is done
- ADC3 - Stream0 CH2, ADC digitizing eigth channels, 32 times before DMA Stream is done (we use it for oversampling calculations)
- SDIO - Stream3 CH4
ADC1 and ADC3 are TIMer triggered (TRGO), repeatedly. Both ADCs do convert multiple channels, and the DMA2 neatly stores each of the data values to RAM, where it is picked up inside the DMA Stream complete IRQ.
Specifically the ability to use DMA for ADC work and also for SDIO, was one of the main drivers for the use of F4 at the day
(including the RAM size back then - today I would go for H7, of course, but the HW is out there already).
SDIO is a classic X*512B transfer (multiblock), standard DMA2 code as in examples (with all the unrelated bugfixes ever done - the SDIO is also a wierd critter, but that is a unrelated story).
Now for the set of questions:
- Obviously the DMA2 bug is in silicon, so a FW workaround is required
- Errata suggests to use only one single DMA Stream at a time
- either (1) move the ADC handling to MCU, that is to use IRQ and not DMA
- or (2) disable ADC DMA access just when SDIO takes over DMA, and re-enable it afterwards - is this even possible ?
Variant (1) is not great at all, as there will be an IRQ call for each every finished conversion, and also there is the possible uncertainty to which ADC input channel the actual data in the register belong.
On the other hand, I suppose only through this way, there won't be any ADC samples lost,
yet I will loose the precious MCU cycles.
Please help me out with (2):
"(2) disable DMA2 for ADC during SDIO DMA access"
How to precisely do that ?
I would expect that I'd call the DMA_Cmd(DMA2_StreamXXX, DISABLE);
Will this finish the DMA transfer half-way, or will it wait for the whole transfer to go through ?
I suppose I will also need to wait for a verification of a disablement, how to do that ?
And finally, how to re-enable the DMA2 for the ADCs ?
Just by issuing the "Stream enable" DMA_Cmd ? or is there more required (to clear some flags, or what) ?
(note that the ADC will keep converting regardless on the DMA Stream state, as all the ADCs are continously TRGO triggered).
Or,
would it be wiser to disable the ADCs themselves ?
Or, do both and disable ADCs and the DMA2 for ADCs ?
That would ge to be too much overhead already, and it will be losing samples . . .
So, in general, any advice is very welcome,
and I'm sure other F4 users will benefit from this as well.
regards,
a.
---
EDIT: invalit bus name was provided, deleted the line to remove confusion. Otherwise, the content stays the same.