Hi, I'm using the F446RE Nucleo for an application.
After many hours of work, I have decided that using two HAL drivers that share a DMA stream on different channels is a bad idea. Is this common knowledge?
I thought there was this "arbiter" that according to the STM32F4 reference manual:
"An arbiter manages the 8 DMA stream requests based on their priority for each of the two AHB master ports (memory and peripheral ports) and launches the peripheral/memory access sequences."
Maybe I have this backwards? The DMA arbitrates between streams that are active, right? Can it arbitrate between different channels on the same stream? The priority is defined by the stream, yeah? So what sort of behavior should I expect for multiple channels requesting access on the same stream?
So, when I use spiSend() when the UARTD4 driver is active in the application, the thread will transfer one byte over SPI and then suspend indefinitely. Seems like a DMA failure, right?
SPI2_tx is on channel 0 of stream 4 on DMA1, and UART4_tx is on channel 4 of the same.
I've found that I simply cannot actively keep both drivers alive at the same time. I must shut one down to use the other. This makes use of SPI2 in one thread difficult to use when UART4 is used in another. The DMA has become some kind of shared resource, for which I cannot control exclusive access.
This seems like a bad thing.
1) Is this common knowledge, and I should look to use a different UART or SPI peripheral? Or is this a HAL limitation? ST limitation?
2) Is this just me not using the HAL correctly? Or am I expecting too much of this micro?
3) Other ways around this? I could have the two threads share use of a mutex to protect the DMA, and prevent both drivers from being used simultaneously, but I just don't want to. Mutexes and semaphores are bugs waiting to happen. I try to stick with synchronous and asynchronous messaging to protect data, and I can usually expect to keep my peripherals up and running the whole time. It seems like a waste of time to re-configure and then shutdown the peripheral every time I use it.
What do you all think? Do you have any suggestions for me?
Am I just being an idiot here? Am I missing something more obvious?
Using driver that share DMA streams
Moderators: RoccoMarco, barthess
- Korken
- Posts: 270
- Joined: Wed Apr 02, 2014 4:09 pm
- Location: Luleå, Sweden
- Has thanked: 5 times
- Been thanked: 6 times
- Contact:
Re: Using driver that share DMA streams
This is a limitation of the DMA peripheral.
When you setup the DMA, you do it per Stream so (psuedo code):
This means that you can only set up one Channel at a time per Stream.
If you want to share DMA Streams, one driver may only use a stream at a time.
And sharing must be done through enabling / disabling conflicting drivers.
Or use DMA on one driver, and interrupts on another (if supported by the driver).
When you setup the DMA, you do it per Stream so (psuedo code):
Code: Select all
DMA1_Stream4->config = USE_CHANNEL_7 | SETTINGS;
This means that you can only set up one Channel at a time per Stream.
If you want to share DMA Streams, one driver may only use a stream at a time.
And sharing must be done through enabling / disabling conflicting drivers.
Or use DMA on one driver, and interrupts on another (if supported by the driver).
- Giovanni
- Site Admin
- Posts: 14457
- Joined: Wed May 27, 2009 8:48 am
- Location: Salerno, Italy
- Has thanked: 1076 times
- Been thanked: 922 times
- Contact:
Re: Using driver that share DMA streams
Drivers can share DMAs even if it is not recommended.
You need to start/stop drivers at runtime, drivers sharing a DMA must never be started at the same time (an assertion is triggered, if assertions are enabled).
Giovanni
You need to start/stop drivers at runtime, drivers sharing a DMA must never be started at the same time (an assertion is triggered, if assertions are enabled).
Giovanni
Who is online
Users browsing this forum: No registered users and 43 guests