0
\$\begingroup\$

I am trying to use the output of COMP2 to trigger the One-Pulse mode of a timer (in my example TIM4, but it's quite flexible if it needs to change to another timer) on the STM32L1 series.

In the reference manual, the explanation for the One-Pulse mode uses TI2FP2 as the timer trigger, which is linked to the Input Capture on channel 2 of the timer, however the output of the comparator can only be redirected to Input Capture on channel 4 (except for TIM10 but it doesn't have a second channel to output the PWM on...), or to OCREF Clear.

I have tried redirecting the COMP2 output to:

  • “OCxREF Clear” of TIM4,
  • the Input Capture 4 of TIM4,
  • the Input Capture 4 of TIM3 and using ITR2 as the TIM4 trigger (ITR2 is TIM3 when used on TIM4)

but none of those options worked.

Should any of these configurations have worked and I just didn’t set them up properly?

Am I supposed to do it differently?

Is there no way to connect the two directly and I should for example start the One-Pulse mode from the COMP2 interrupt?

\$\endgroup\$
1
\$\begingroup\$

Looking at the timers' block diagram I couldn't find a direct method either, there are apparently no signals going from CH4 to the trigger unit.

If you'd like to avoid interrupts, and have a suitable free DMA channel, you can use that to start another timer. You can use TIM2_CH4 or TIM3_CH4 (I'm using TIM3 in the example), but there is no DMA channel for TIM4_CH4. You can stick to TIM4 or use any other timer as the target.

  • Set up TIM4 for One-pulse mode, but do not start it yet. Figure out what value would go into TIM4->CR1, and store it in a memory variable, e.g. volatile uint8_t tim4_cr1_start = TIM_CR1_OPM|TIM_CR1_CEN; for the simplest case.
  • Set up DMA1_Channel3, memory address is &tim4_cr1_start from above, peripheral address is &TIM4->CR1, transfer length is 1. Use 8-bit mode, enable circular mode.
  • Set TIM3_CH4 to input capture, select polarity etc in TIM3_CCER and TIM3_CCMR2.
  • Enable CC4DE, capture/compare 4 DMA request in TIM3->DIER.
  • Start TIM3.
  • Redirect COMP2 output to TIM3_CH4 (you could use TIM2_CH4' too, but there is no DMA channel forTIM4_CH4`).

Now, a comparator event would trigger a capture on TIM3_CH4, which would instruct DMA to write a suitable value to TIM4->CR1. As the DMA is set to circular mode, it would copy the same value to TIM4->CR1 on every subsequent capture event.

\$\endgroup\$
  • \$\begingroup\$ Thank you for the explanation, I haven't really used the DMA before, so it's definitely a good opportunity to learn how to use it! Do you know how this solution would compare to using interrupts in terms of delay between the COMP2 output changing and the One-Pulse mode starting on the output pin? \$\endgroup\$ – Benoît Vernier Oct 22 '18 at 0:51
  • \$\begingroup\$ @BenoîtVernier Interrupt entry in a Cortex-M3 takes at least 12 cycles, then a minimal handler implementation would take at least another 5 cycles (1 for MOVS, 2 for LDR and 2 for STR). It's a theoretical minimum, I'd say 20-25 cycles are realistic. I don't really know about DMA latencies, I'd guess 3 or 4 cycles, and I'd be quite surprised if it would take more than 5. Then the timer needs maybe another 2 cycles to start in both cases. \$\endgroup\$ – berendi - protesting Oct 22 '18 at 8:25
  • 1
    \$\begingroup\$ @BenoîtVernier Actually an interrupt entry can be faster if another interrupt handler is finishing at the exact right moment (see tail chaining). The point is, interrupt latency can be uncertain to +/- 6 cycles, DMA delay should be constant if you give this channel the highest priority level. \$\endgroup\$ – berendi - protesting Oct 22 '18 at 8:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.