cancel
Showing results for 
Search instead for 
Did you mean: 

Has anyone ever gotten DMA2 to update TIM1 or TIM8 CCRx registers to work ?

Gudgel.boB
Senior

I've been trying to get any DMA2 stream-channel (presently TIM1_UP) to update TIM1 CCR1,2, or 3 registers using a table in memory for a while now with no luck. Before adding some of my code here, I thought I would see if anyone has ever actually gotten that to work before.

The manual is vague and there are a few web pages that mention passing capture registers to memory (peripheral to memory) and supposedly the other way around should work.

I have ADC1, ADC2, ADC3 succesfully transfering to memory though. That seemed easy compared to this.

I have the DMA2 Stream5 NDTR doing the right thing when TIM1 is enabled to do so but the data, IF coming from memory to peripheral is going out into space somewhere.

Direct mode, FIFO mode, Double buffer mode.... Nothing seems to put data into any of those CCR registers from the data array 

A software example of this would be really nice if anyone knows of one out there. There is a thread from 2016 where Clive pointed to one I think but that link is now dead.

A couple of additional questions...

The TIM1&TIM8 DMAR register (for full transfer)...

What does that mean exactly, "for full transfer" ? Is the DMAR necessary for loading CCRx from memory in DMA mode ?

Why would I see others (code examples on the interweb) do this...

DMA2_Stream5->PAR =  (uint32_t) &TIM1->DMAR;

DMAR is supposed to contain the start of the peripheral address, why would they want the address of the DMAR in the DMA2 Peripheral Address Register ?

And what exactly do they mean by peripheral control or DMA controller control ? Is that the trigger only ?

Thanks,

boB

18 REPLIES 18
S.Ma
Principal

Have done this with STM32F437 in standard lib on Timer8, only on 1 channel to generate multi-pulses triggered by incoming edge signal.

The timer trigger is the ADC trigger and the output compare pulse is used to dynamically switch an op-amp.

Multiple timers for multiple channels.

The table of compares must be incremental and follow the timer's progression.

If the value written by the DMA is out of range, all stops.

The code is now old and didn't invest energy to convert STD lib into HAL... maybe there are some examples in Nucleo Cuber Timer + DMA projects...

Gudgel.boB
Senior

Thanks. Yes, I have seen an example I think of ADC triggering a value to a TIM1 or TIM8 CCRx register. I'm trying to use the Timer update..... Some kind of Timer update to trigger the loading of a value from memory to the CCRx register(s). I'm pretty sure that if and when I get ANYTHING to load into there, I can get the rest of things working. But, so far, not luck going memory to TIM1 (or TIM8) peripheral register.

I am trying NOT to use the HAL method. It is much more understandable for me to just load the registers and their bits directly. I had horrible luck with TIM1,TIM8 DMA register loading using HAL. However, the ADC portion used the HAL method and worked OK.

Also, I have had TIM1 and TIM8 working as planned while loading CCRx registers by way of timer interrupt.

Definitely had DMA2 working on TIM1 and TIM8 of F2/F4 series parts

TIM1_UP -> DMA2 Stream5 Channel6

Probably a bit in TIM1->DIER

Registers like CCRx/CNT/ARR are HALF-WORD

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Gudgel.boB
Senior

Thanks guys ! Oh, and I am using a STM32F446E part

Yep, I had enabled the UDE and/or TDE bit in DIER and set for half words (16 bits).

Still not exactly sure of the difference between

UDE: Update DMA request enable and

TDE: Trigger DMA request enable

But I am surmising that UDE makes the TDE go ???? Meaning that the Update is when the counter over/under flows and

then that will TRIGGER the DMA2 Stream5 Channel 6 slot ?? Any clarification would be great.

AHAAA !!! I am NOW getting table data into CCR1, CCR2, CCR3 and CCR4 !!!!!!

Turns out I was trying to use a pointer to the TIM1 structure (BASE) and adding the offset to that which should (maybe) have worked BUT it was of course sending my values off into space. No WONDER ! NOVEMBER !!!

So, another question...

WHY do some people do this ?....

DMA2_Stream5->PAR =  (uint32_t) &TIM1->DMAR;

What does the DMA controller do with "TIM1&TIM8 DMA address for full transfer (TIMx_DMAR)" ????

It was looking kind of like the DMAR register was optional for some reason or another. What do they mean by "for full transfer" ?

Thank you for your wisdom !

Gudgel.boB
Senior

Oh, and JW... I had found and gone several times to the Hello World link you posted. I think I had also checked out the EWARM code. I suppose nothing could have helped me with my issue of trying to work with the pointer to the structure of the timer registers rather than the definition of the actual address of the TIM1 register base except a coworker came and helped me with my PAR loading.

Would still like to know, if possible, about those registers like DMAR though.

Thank you !

TIMx_DMAR is not a register - it's a ''window'' into other TIM registers for indirect accesses, addressed by TIMx_DCR.DBA.

TIMx_DIER.TDE enables to trigger a DMA transfer (and .TDI enables triggering an interrupt) when a trigger arrives through the slave-mode controller of the timer (see TIMx_SMCR.TR).

JW

Gudgel.boB
Senior

Thank you JW !

Now THAT's an answer that I would not have known unless you said this. (about it being a window)

DMAR/DMAB is R/W so not needing to use it was not obvious to me although I was starting to get that view.

And, what is it ? DMAR or DMAB ? My IAR debugger shows a different separate for DMAR vs. DMAB but they "appear" to me to be the same thing, almost but not really.

"

Bits 15:0 DMAB[15:0]: DMA register for burst accesses

A read or write operation to the DMAR register accesses the register located at the address (TIMx_CR1 address) + (DBA + DMA index) x 4

"

I really wish there was better (more) documentation on how this logic all works.

There is also no debug mode for DMA and so things just happen when they are allowed to by the enable bits.

Next to see if I need to use timer 1&8 interrupts to change DMA data values or if I can get Double Buffer DBM to help me by using the CT bit.

There are a lot of bits and modes to get straight

> And, what is it ? DMAR or DMAB ?

DMAB denotes the active bits in DMAR. Maybe there are some marginal cases when it does matter, but as long as you know whether your timer is 16- or 32-bit and read/write to/from DMAR accordingly, you can forget about DMAB.

> There is also no debug mode for DMA and so things just happen when they are allowed to by the enable bits.

Well, it's actually only about making things happen at the pace you want to. And the key to this is to trigger the DMA by a signal you can control "manually". For example, set it to trigger from an unused CC channel (for TIM1/8 it may be a different channel/stream, but how does that matter for the sake of experiment?). And you can manually control output level of that channel through its mode settings in CCMRx. In that way, you can "single-step" the DMA, observe its registers and observe the consequences of its working - and all this in the debugger, you don't need to write a single line of code. (Note, that in DMA, NDTR will change, but the address registers, as displayed by debugger, won't,).

> I really wish there was better (more) documentation on how this logic all works.

I really wish there was better (more) documentation.

ST gave us Cube instead.

JW