cancel
Showing results for 
Search instead for 
Did you mean: 

Automatic re-enabling of DMA channel upon completion of transfer

pmjobin
Associate II

Hello,

I have configured a DMA channel to perform a memory-to-memory transfer triggered by EXTI. I would like to automatically re-arm channel at the end of every completed transfer so that it is ready to process the next EXTI trigger event without any CPU intervention. What are the possible avenues to achieve this goal?

Thank you very much for your assistance,

P-M

1 ACCEPTED SOLUTION

Accepted Solutions
BarryWhit
Senior III

Update:

reading sections 17.4.12 and 17.4.7 of RM0456 (Rev 5), It's possible to have an external trigger for transfers, and configure the DMA to run a "recursive" linked list, meaning that the last entry points back to the first one. The GPDMA is configured in "run-to-completion" mode (GPDMA_CxCR.LSM =0), and that way the DMA transfer never "completes". You can continue sending external triggers indefinitely.

 

I'm not sure how you plan to use this, but it looks possible.

 

The Juggler's Solution:

 

The DMA peripheral is allowed to write to the memory-mapped registers of various peripherals on the chip. With the "bit-banding" support in STM32, you can also have DMA write to specific bits (*). Combine this with the Linked-List DMA functionality and, with some jiggery-pokery, you could probably arrange things as you wish.

 

It should be possible to craft a write-white-where primitive using any comms peripherals with these tools, as long as you have sufficient control over the external host in terms of on-the-wire protocol and wait states.

 

One possible way (I'm just speculating here) is to have:

wait for EXTIx -> EXTIx Edge->trigger DMA Ch1 -> ll1 (clear TC flag for DMA ch2) -> ll2...n (do tha thingz) -> DMA_CH1_TC event->Trigger DMA CH2-> (clear TC flag for DMA ch1) -> (da capo).

 

(*) as JW rightly points out, I was wrong. Bit-Banding is neither available on the STM32U5, nor is it usable with DMA on chips where it is available.

- If someone's post helped resolve your issue, please thank them by clicking "Accept as Solution".
- Please post an update with details once you've solved your issue. Your experience may help others.

View solution in original post

8 REPLIES 8
BarryWhit
Senior III

a repetitive memory-to-memory transfer triggered by an external interrupt seems like a very strange thing to want to do.

Having an EXTI rate so high that you can't afford  the cycles to clear a flag in the ISR seems like a very strange situation.

 

Can you give more details about the context? Perhaps if you tell us what you're trying to achieve instead of how you're trying to achieve it, we could suggest a different way.

 

> Section 17.4.17 of the STM32U5 reference manual suggests that the transfer complete event of the channel can be >programmed as a trigger, allowing autonomous transfer scheduling without the need to clear TCF.

Ok...

>However, my primary concern is synchronizing the DMA transfer with the EXTI event.

This wording is a bit confusing. I guess what you're trying to say is that althogh you found a way to the TC event to re-trigger a transfer, what you actually want to is to have the TC event "self-clear", so the next EXTI trigger can initiate a new transfer...

Which again raises the question - what are you trying to do? if you're moving data around, you must want to do something with it. For that, you need to somehow synchronize between the TC event, the processing of data and, to avoid overrun, the arrival of the next EXTI.

If your ISR rate is so high that you can't afford the few cycles it takes to clear the flag, how do you plan to do any processing of the data before it is overwritten by the DMA triggered with the next EXTI event?

 

Possibly, something is not quite right with your system design, and you need to tell us a lot more about your application (external sources and events, required throughput, real-time constraints)

 

 

- If someone's post helped resolve your issue, please thank them by clicking "Accept as Solution".
- Please post an update with details once you've solved your issue. Your experience may help others.

> Having an EXTI rate so high that you can't afford  the cycles to clear a flag in the ISR seems like a very strange situation.

 

The situation involves the STM32 operating as a slave device that responds to frequent bidirectional (read/write) data transfer requests initiated by an external host. Such transactions are tiny but occur very frequently. If each transaction were to involve the CPU core, it would likely overwhelm it and thus, limit its availability for other tasks and/or significantly increase the latency of the transactions. Therefore, my objective is to fully automate DMA transfers to alleviate this issue.

 

This wording is a bit confusing.

 

Sorry for the poor wording of my original question. I wrote the post late at night and hadn't fully clarified my thoughts. I have since edited the original question to remove superfluous details and hopefully better convey my intent.

 

> I guess what you're trying to say is that althogh you found a way to the TC event to re-trigger a transfer, but what you actually want to is to have the TC event "self-clear", so the next EXTI trigger can initiate a new transfer...

 

Yes, exactly.

 

If your ISR rate is so high that you can't afford the few cycles it takes to clear the flag, how do you plan to do any processing of the data before it is overwritten by the DMA triggered with the next EXTI event?

 

The ARM processor does not need to perform any processing upon completion of individual DMA transfers. The closest analogy I can think of is the host port interface (HPI) implemented in certain DSP models, where part of the DSP's address space is made accessible to an external host. The only ingredient still missing from my current implementation of such mechanism is a method to autonomously re-arm the DMA channel without CPU intervention.

 

Ref: https://www.ti.com/lit/ug/spru578c/spru578c.pdf?ts=1720876823624

 

Thanks,

P-M

BarryWhit
Senior III


> The situation involves the STM32 operating as a slave device that responds to frequent bidirectional (read/write)

> data transfer requests initiated by an external host.

 

So you're talking about transferring data between an external host and the STM32. This would not usually be referred to as "memory-to-memory" DMA within the STM32 conceptual universe. (i.e. "memory-mapped" is not the same thing as "memory")

- If someone's post helped resolve your issue, please thank them by clicking "Accept as Solution".
- Please post an update with details once you've solved your issue. Your experience may help others.
BarryWhit
Senior III

Update:

reading sections 17.4.12 and 17.4.7 of RM0456 (Rev 5), It's possible to have an external trigger for transfers, and configure the DMA to run a "recursive" linked list, meaning that the last entry points back to the first one. The GPDMA is configured in "run-to-completion" mode (GPDMA_CxCR.LSM =0), and that way the DMA transfer never "completes". You can continue sending external triggers indefinitely.

 

I'm not sure how you plan to use this, but it looks possible.

 

The Juggler's Solution:

 

The DMA peripheral is allowed to write to the memory-mapped registers of various peripherals on the chip. With the "bit-banding" support in STM32, you can also have DMA write to specific bits (*). Combine this with the Linked-List DMA functionality and, with some jiggery-pokery, you could probably arrange things as you wish.

 

It should be possible to craft a write-white-where primitive using any comms peripherals with these tools, as long as you have sufficient control over the external host in terms of on-the-wire protocol and wait states.

 

One possible way (I'm just speculating here) is to have:

wait for EXTIx -> EXTIx Edge->trigger DMA Ch1 -> ll1 (clear TC flag for DMA ch2) -> ll2...n (do tha thingz) -> DMA_CH1_TC event->Trigger DMA CH2-> (clear TC flag for DMA ch1) -> (da capo).

 

(*) as JW rightly points out, I was wrong. Bit-Banding is neither available on the STM32U5, nor is it usable with DMA on chips where it is available.

- If someone's post helped resolve your issue, please thank them by clicking "Accept as Solution".
- Please post an update with details once you've solved your issue. Your experience may help others.

This would not usually be referred to as "memory-to-memory" DMA within the STM32 conceptual universe. 

 

In my original post, I referred to it as 'memory-to-memory transfer' because that's how I must configure the DMA channel (with SWREQ = 1). This transfer involves moving data between two memory locations (specifically, SRAM and FSMC), and it does not rely on a peripheral initiating the transfer via REQSEL but rather an EXTI trigger.

 

> One possible way (I'm just speculating here) is to have:

 

Yes, I had considered a solution involving a second DMA channel to clear the TC flag of the first one (and vice-versa). However, this approach would introduce additional traffic on the already crowded AHB bus, which I aimed to avoid. I was hoping for a more direct method to rearm the DMA channel after each transfer, but I suspect there is none. Therefore, I will mark your solution as 'accepted,' as I believe it provides the only viable answer to my question.

 

> Caveat is that you've already decided on a particular solution for the real problem you're trying to solve, and you're asking for help implementing the solution, not for advice on the best way to solve the problem. 

 

My choice of approach was primarily dictated by how the external host (which I have no control over) communicates with the outside world (via a parallel bus with multiplexed address/data). A more conventional solution would involve setting up a shared memory bank between the host and the STM32, managing access with a bus arbiter implemented in programmable logic. Instead, I thought I could get away with the somewhat ugly hack of using the internal SRAM of the STM32U5 (which there is plenty of) as the shared memory and relying on its own bus controller to act as the arbiter. It's frustrating to come so close to a working solution, only to be tripped up by one last implementation hurdle.

 

> Asking for the latter may have gotten you some useful suggestions on alternative approaches.

 

I'll keep this advice in mind for future questions.

 

Thanks again for your help,

P-M

I noticed your new update immediately after I sent my last reply. I'll review the sections you outlined more carefully but I think it could work for my problem. Thank you for investigating this!

 

Update: I tested the circular linked list transfer approach suggested by BarryWhit and can confirm that the loop allows indefinite repetition without needing to reset the TC flag, which is exactly what I wanted. Each item of the linked list that is conditioned by a trigger will block until the specified trigger event occurs. Thanks again.

Just a small tangential correcton:

> With the "bit-banding" support  in STM32, you can also have DMA write to specific bits.

There is no bit-banding on 'U5/Cortex-M33. In fact, bit-banding is property of the memory interface of Cortex-M3/M4 and as such, is not available for DMA in mcus employing one of those two cores either.

JW

BarryWhit
Senior III

This transfer involves moving data between two memory locations (specifically, SRAM and FSMC)

 You're right. I wish you had simply mentioned you're relying on the FSMC in the OP. 

 

> JW Wrote:

There is no bit-banding on 'U5/Cortex-M33

 

Thank you for the correction, @waclawek.jan .

- If someone's post helped resolve your issue, please thank them by clicking "Accept as Solution".
- Please post an update with details once you've solved your issue. Your experience may help others.