cancel
Showing results for 
Search instead for 
Did you mean: 

Advice on STM32U5 multiple timer configuration

draeman-syn
Associate

I'm struggling with how to use the timers to achieve certain behavior and am looking for some advice. First I'll describe the purpose, then how I tried to approach it, and then why I'm stuck.

I need a 32-bit timebase that counts up at exactly 48kHz and always runs, rolling over from 0xffffffff back to 0. This timebase is used to precisely "schedule" the start of DAC and/or ADC conversions at some future counter value. For example, if the current counter value is 12345, I might want to start DAC conversion at counter value 20000. Optionally, I might also want to start ADC conversion at counter value 20100.  The DAC and ADC are scheduled independently but may overlap. Once triggered, the DAC/ADC channels should continue running until disabled by software. It's important that the timebase, DAC sampling, and ADC sampling are all synchronized at 48kHz such that they maintain a consistent relative phase offset, even across conversion windows. Since my application would be very sensitive to relative timing jitter, I am trying to do as much as possible via hardware events. In a nutshell, I want to use one always-running timer to precisely time-gate the start of continuous ADC and DAC windows.

My first thought was to configure TIM2.PSC for a 48kHz counter rate and set TIM2.ARR to 0xFFFFFFFF, so TIM2 is the 32-bit timebase. Then I'd use its CH1 and CH2 in output compare mode to trigger the start of two other timers  (TIM4 and TIM5) that would clock the DAC and ADC, respectively. For example, TIM2.CCR1 is the future counter value to start the DAC conversion. TIM4 and TIM5 would be configured as slaves to TIM2 and would be triggered to start via TIM2's CH1 and CH2 events. Then to stop the DAC/ADC, software would later disable TIM4/TIM5.

The problem here is that TIM2 only has one trigger output (trgo), so I don't see a way that TIM2 can use OC1 as a trigger to TIM4 while simultaneously using OC2 as a trigger to start TIM5. Or, maybe I'm misunderstanding the signals. For now I'm going to just start it from an ISR, but any thoughts on how to accomplish this would be much appreciated - happy to discuss as raw registers or as CubeMX HAL nomenclature.

4 REPLIES 4

I may have misunderstood you, but it sounds to me, that you want to trigger DAC and ADC from one or more timers which have a 1/48kHz period.

So, I would set up some suitable timer (let's call it TIMx) to have that period, and have that as timebase for TIM2 instead of using TIM2 prescaler. At the same same, I would chose TIMx so that it could trigger DAC and ADC transfers possibly from two of its channels, to allow for phase shift between them within the 1/48kHz period.

To enable/disable ADC/DAC sampling, it's then enough to change the given TIMx_CHx channel's Compare Mode in TIMx_CCMRx.OCxM from Frozen to PWM and vice versa. And to achieve that, you can trigger a DMA transfer by TIM2's CC at the proper moment, which would transfer a suitable value from a buffer in memory to TIMx_CCMRx.

If this is not what you intend to achieve, I may have misunderstood your intentions - you may perhaps try to sketch some example timing diagram then.

JW

Thanks for the response - using the TIM CC's DMA capability to alter a controller register is not something I had considered. I'll take a closer look at that, and if I'm still stuck I'll follow-up with a diagram.

Cheers.

Thanks again for the idea. I think it would achieve the behavior I'm looking for, but I've run into a few roadblocks with it - please let me know if I've overlooked something..

  1. I don't see a way for TIM2 CC DMA to write a register in a different timer instance (TIMx). The TIM DMA mechanism seems to only support specifying a starting offset within the same TIM instance.
  2. It also seems like each TIM can only configure one DMA at a time (since there is only one TIMx_DCR register). In my case I'd need to drive PWMs to the DAC and ADC from separate CC channels, since the decision to enable each of them is independent (as determined by two distinct TIM2.CCRx registers).
  3. It seems like the DAC can only be triggered by a tim_trgo signal, not directly from a tim_oc signal (see attached table from RM0456). I think this is the crux of why I'm spinning my wheels on this. The ADC does seem to have a few options for tim_oc triggering.

Thank you.

1. and 2. - you are confusing DMA - which is a standalone unit, agnostic of what are the source and destination points aimed at, memory or any of the peripherals - with the TIM_DMAR/DCR mechanism, which is intrinsic to timers and comes into play only if one of the DMA  pointers points specifically to TIMx_DMAR.

I suggest you to perform a couple of simple exercises first, to get the feeling of things - e.g. set a DMA channel to be triggered from a very slowly running timer, say generating one trigger per second, and let it transfer data from one array in memory to an other one, while observing the destination array in debugger. 

3. Then let DAC be triggered from TIMx_TRGO bound to some of the channels, and ADC from OC of a different channel. You can have two mitigator synchronized timers, too, but that's one more nontrivial challenge extra. 

JW