-
Notifications
You must be signed in to change notification settings - Fork 72
Description
Hello,
I think this question might also be suited in a forum post. I am using a STM32F3-Disco in my current project so I thought that I can also ask this here.
I am currently planning on how to perform variably sized transfers using DMA + IRQ + RTIC. According to some forum posts, this is definitely possible using the IDLE line or the Receiver Timeout IRQ by the USART peripheral. More specifically, I wanted to have one RTIC task which uses DMA to send all TX data, and one RTIC task to receive variable sized RX packets, which are only limited in their maximum size.
Unfortunately, I have not really found an example for this in Rust yet and I only have experience with variable sized transfers using a combination of FIFO + IRQ on a smaller Cortex-M0 based system. Most of the DMA based API I have found uses the read_exact
API which uses a fixed buffer size.
I've looked around and experimented myself a little bit. I have found this code snippet: https://github.com/kalkyl/f303-rtic/blob/main/src/bin/serial.rs , which goes into the direction of what I require.
Some thoughts I had:
- TX: is usually a little bit easier. I have a RTIC task which reads from a heapless queue or some other form of queue and sends any contained frames with DMA. My first approach would be to simply wait until the transfer is complete because I'd like to unblock the shared serial as soon as possible. The second approach instead uses a transfer complete IRQ, but then I am not fully sure how to access the USART peripheral without trickery or hacks just to read IRQ events, for example for pending RX
- RX: I configure a receive timeout IRQ and then initiate a DMA transfer with the maximum expected packet length. When receiving a recv timeout IRQ or a transfer complete, I stop the DMA transfer (for recv timeout) and restart a new one with the maximum expected packet length. I pass the read packet into a heapless queue or some other form of queue which is processed by another task.
Now, from what I have see from the STM32F3 HAL docs, this will not be straightforward.
One problem is that I am forced to split the serial struct for DMA transfers, as the transfer struct takes ownership of the RX or TX part. This definitely makes sense, but I need the serial struct to check IRQ events . I could retrieve those using the join method, but that will never be possible because a DMA transfer for RX will practically be active permanently, and thus the RX part will always be unavailable, being cached in some transfer struct unavailable to the TX task. What is the common approach when facing a problem like that? One idea I had was to adapt the split function to return the USART peripheral so I can use it at my own peril for things like this.
Maybe someone has a better idea how to do this? Maybe there is also some other aspect I am forgetting here.. I checked the available interrupts of the STM32F303 again. I guess the core problem is that the interrupt register is used both for RX and TX, although some of the events can be checked independently for RX and TX..