cancel
Showing results for 
Search instead for 
Did you mean: 

HRTIM in PWM output mode: How do I use DMA for all 12 channels?

MTall.3
Associate II

I am using the STM32G484 microcontroller to output twelve high resolution PWM signals with the HRTIM timer module. All timers have the same constant period and and the CMP1xR and CMP2xR registers for all six timers are updated after every repetition via an interrupt (fired by the master timer repetition event). The PWM signals are also periodic and repeats after 64 updates.

If I had only one output, I could configure a DMA in circular mode with 64 samples in size and then let it increment the memory address and have a fixed peripheral address. Then the CPU wouldn't have to do any job at all except for when the periodic signal changes, which is upon user interaction.

Now the problem is, I can't seem to find a way to do the same for all twelve channels because there are two channels per timer and the DMA configuration is one per timer, which means I can only do this for up to six channels.

Is there anything I miss here? How can I update CMP1xR and CMP2xR with new values every repetition for all six timers by using one or several DMAs? Is it even possible or are six channels the limit?

Thanks.

4 REPLIES 4
TDK
Guru

You can use a DMA burst to update multiple registers during the same event. See "27.3.23 DMA" in the reference manual. The BDMADR register will demux data into the appropriate registers based on the registers selected in BDTxUPR.

0693W00000KbByzQAF.png

If you feel a post has answered your question, please click "Accept as Solution".
MTall.3
Associate II

Thank you for your reply.

Ok, this looks promising. So if I understand it correctly, I would enable burst mode and select the master timer repetition as trigger source, then add a DMA source connected to the master timer (circular mode, incremental mem, no incremental peripheral), then configure the master timer to write to HRTIM_BDMADR, size of DMA transfer set to 64*12=768 half words.

Then I would go to each timer and enable the burst mode controller and select the registers I want to update. In memory I would have

uint16_t data[64][12] =

{

{ // t = 0

CMPA1R,

CMPA2R,

CMPB1R,

CMPB2R,

...

CMPF1R,

CMPF2R

},

 { // t = 1

CMPA1R,

CMPA2R,

CMPB1R,

CMPB2R,

...

CMPF1R,

CMPF2R

},

... // t = 2 ... t = 63

};

Then at every time the master timer repeats, it will trigger a start of the burst DMA controller, which will request 12 half words from memory and demux it out on the corresponding registers and after 64 such events the source address wraps around and everything restarts.

Is this correct?

TDK
Guru

That is my understanding as well.

If you feel a post has answered your question, please click "Accept as Solution".
MTall.3
Associate II

Thank you for your help, it's working now.

After a few hours of hacking around, I realised I had mixed up "Burst Mode Configuration" with "Burst DMA Controller". That being said, it was even simpler to make it work as the Burst DMA Controller is always active. It was just a matter of enabling "Burst DMA Configuration", selecting the sources and then enabling one DMA channel that had BDMADR as destination. Apart from STM32CubeMX, having normal DMA already working in the code, the only thing that needed to be changed was the memory layout so that it looked like the one wrote in my previous post.