Timer -> DMA.

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderators: RoccoMarco, barthess

rew
Posts: 380
Joined: Sat Jul 19, 2014 12:59 pm
Has thanked: 2 times
Been thanked: 13 times

Timer -> DMA.

Postby rew » Thu Jul 19, 2018 3:37 pm

Hi,
I want to have a timer trigger a DMA action. The target is a GPIO ODR register.
Thus I can have a 16-bit (or 8bit) wide datapattern on a port. Great!

This has been working great for where the timer creates a regular interval. But now I want to tie the pattern to a timer that handles an encoder. Triggering the DMA on update (most people call it overflow, but that doesn't matter), works too. But I want to trigger on each change of the counter value.

The encoder is connected to TIM3 of my STM32F072.
So to have it work on update, I set TIM3->DIER to UDE 0x100. And I use the TIM3_UP channel on the DMA controller Channel 3. This works.

But when I set TIM3->DIER to TDE, 0x4000, and use TIM3_TRIG channel on the DMA controller (CH 4). it doesn't work. No DMA requests are triggered.

Any suggestions as to what the cause could be?

Here is a dump of my timer.
> dumpt 3
TIM3 at 40000400
CR1=0015 CR2=0000 SMCR=0003 DIER=4000 SR=061F EGR=0000
CCMR1=0101 CCMR2=0000 CCER=0011 CNT=0971 PSC=0000 ARR=0FFF RCR=0000
CCR1=0971 CCR2=096E CCR3=0000 CCR4=0000 BDTR=0000 DCR=0000 DMAR=0015


And here is the DMA channel:
chan4: CCR=2093 CNTDR=0800 CPAR=48000814 CMAR=20000B20


here is what DOES work (but not as I want it):
> dumpd 3
DMA1 ch3 at 40020000 (40020030) ISR=0000000
chan3: CCR=2093 CNTDR=07F8 CPAR=48000814 CMAR=20000B20
> dumpt 3
TIM3 at 40000400
CR1=0005 CR2=0000 SMCR=0003 DIER=0100 SR=061F EGR=0000
CCMR1=0101 CCMR2=0000 CCER=0011 CNT=080A PSC=0000 ARR=0FFF RCR=0000
CCR1=0808 CCR2=0809 CCR3=0000 CCR4=0000 BDTR=0000 DCR=0000 DMAR=0005

I apparently twisted the encoder about 32000 counts, as 8 update events at 0x1000 have happened.

Update: Setting the ARR to "1" works at half the required speed. Setting the ARR to zero does not cause an update event each time the counter tries to reach "1" and is reset to zero.

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Timer -> DMA.

Postby Giovanni » Thu Jul 19, 2018 6:18 pm

Not sure but ARR set to zero stops the counter apparently, not sure if it is legal to do that.

This could also be asked in the ST support board and see if somebody has a solution.

Giovanni

rew
Posts: 380
Joined: Sat Jul 19, 2014 12:59 pm
Has thanked: 2 times
Been thanked: 13 times

Re: Timer -> DMA.

Postby rew » Thu Jul 19, 2018 8:25 pm

Yeah... But the ST support forum is down for a week. "maintenance" is what they say.....

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Timer -> DMA.

Postby Giovanni » Thu Jul 19, 2018 9:19 pm

It has been down for years for me, I stopped trying to understand how it works after the last iteration.

Giovanni

User avatar
FXCoder
Posts: 384
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 180 times
Been thanked: 130 times

Re: Timer -> DMA.

Postby FXCoder » Sun Jul 22, 2018 5:56 am

The way I use TIM to DMA from (or to) GPIO is with capture mode.
The TRIG source to the TIM fires capture (value of CNT is irrelevant) and runs DMA which is setup to transfer the GPIO data.

I used this technique to build a pseudo DCMI interface on an STM32 w/o DCMI.
I use DBM and DMA cache to get required performance.

rew
Posts: 380
Joined: Sat Jul 19, 2014 12:59 pm
Has thanked: 2 times
Been thanked: 13 times

Re: Timer -> DMA.

Postby rew » Sun Jul 22, 2018 9:19 am

From my experiments, I didn't get the trigger to work in encoder mode.

I have since realized that my table has only a few changes. So I can set a channel to output mode, disconnect the pin, but use the compare interrupt and DMA request to cause the DMA to update the output port, and then use the interrupt to set the new compare point.

For every cycle I'm going to need about 8*6*2 = about 100 changes. So instead of keeping a 10000 entry table with the output value for all of the possible positions, I'm going to keep two tables: The positions where the output changes, and the new output value.

By using the DMA to update the outputs, I get a reliable quick update. About 200ns from the edge of the signal from the encoder with the current settings. I'm probably going to increase the filtering in the end. That's going to introduce a longer delay, but those don't matter for the application.

Then it seems to take about 2.5 microseconds for the interrupt to activate, and my current code runs for 0.5 microseconds. With an expected encoder update frequency of 10kHz, maybe double that, I'm plenty on-time to get the next compare updated before the next count event (50 microseconds) (getting this done on-time is required should successive counter values require a change. On the other hand, chances of that being required is low with only 100 changes on 10000 possible positions... Hmmm birthday paradox: chances are bigger than you expect, without doing the math, I'd guess about 36%!!! But that's with 100 random changes, and my application is not random....).


Return to “STM32 Support”

Who is online

Users browsing this forum: No registered users and 12 guests