rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
microsecond_timer_stm32.cpp
Go to the documentation of this file.
1/**
2 * @file microsecond_timer_stm32.cpp
3 *
4 * A single upcounting timer (currently TIM5) is used as a single timebase both for time
5 * measurement and event scheduling. This helps reduce jitter by not making another time
6 * measurement at the time of scheduling.
7 *
8 * This implementation only works on stm32 because it sets hardware registers directly.
9 * ChibiOS doesn't support using timers in output compare mode, only PMW, so we have to
10 * manually configure the timer in outupt compare mode.
11 *
12 * @date Dec 1, 2020
13 * @author Matthew Kennedy, (c) 2012-2020
14 */
15
16#include "global.h"
17
18#if EFI_PROD_CODE && HAL_USE_PWM
19
21
22void portSetHardwareSchedulerTimer(efitick_t nowNt, efitick_t setTimeNt) {
23 // This implementation doesn't need the current time, only the target time
24 UNUSED(nowNt);
25
26 pwm_lld_enable_channel(&SCHEDULER_PWM_DEVICE, 0, setTimeNt);
27 pwmEnableChannelNotificationI(&SCHEDULER_PWM_DEVICE, 0);
28}
29
31 pwmDisableChannelNotificationI(&SCHEDULER_PWM_DEVICE, 0);
33}
34
35static constexpr PWMConfig timerConfig = {
36 .frequency = SCHEDULER_TIMER_FREQ,
37 /* wanted timer period = 2^32 counts,
38 * but driver set (period - 1) value to register
39 * also period is uint32_t
40 * So set it to zero so it will overlap to 0xffffffff when writen to register */
41 .period = 0,
42 .callback = nullptr, // No update callback
43 .channels = {
44 {PWM_OUTPUT_DISABLED, hwTimerCallback}, // Channel 0 = timer callback, others unused
45 {PWM_OUTPUT_DISABLED, nullptr},
46 {PWM_OUTPUT_DISABLED, nullptr},
47 {PWM_OUTPUT_DISABLED, nullptr}
48 },
49 .cr2 = 0,
50 .bdtr = 0,
51 .dier = 0
52};
53
55 pwmStart(&SCHEDULER_PWM_DEVICE, &timerConfig);
56
57 // ChibiOS doesn't let you configure timers in output compare mode, only PWM mode.
58 // We want to be able to set the compare register without waiting for an update event
59 // (which would take 358 seconds at 12mhz timer speed), so we have to use normal upcounting
60 // output compare mode instead.
61 SCHEDULER_TIMER_DEVICE->CCMR1 = STM32_TIM_CCMR1_OC1M(1);
62
63 /* TODO: implement for all possible TIMs */
64 if (SCHEDULER_TIMER_DEVICE == TIM5) {
65 /* stop timers clock when core is halted */
66 #if defined(STM32F4XX) || defined (STM32F7XX)
67 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM5_STOP;
68 #endif
69 /* TODO: stm32h7? */
70 }
71}
72
74 // Using the same timer for measurement and scheduling improves
75 // precision and reduces jitter.
76 return SCHEDULER_TIMER_DEVICE->CNT;
77}
78
79#endif // EFI_PROD_CODE
void pwm_lld_enable_channel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width)
Enables a PWM channel.
UNUSED(samplingTimeSeconds)
void portMicrosecondTimerCallback()
uint32_t getTimeNowLowerNt()
void portSetHardwareSchedulerTimer(efitick_t nowNt, efitick_t setTimeNt)
static void hwTimerCallback(PWMDriver *)
static constexpr PWMConfig timerConfig
void portInitMicrosecondTimer()
Type of a PWM driver configuration structure.
uint32_t frequency
Timer clock in Hz.
Structure representing a PWM driver.