9 #if UAVCAN_STM32_TIMER_NUMBER
17 # if (UAVCAN_STM32_CHIBIOS && CH_KERNEL_MAJOR == 2) || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
18 # define TIMX UAVCAN_STM32_GLUE2(TIM, UAVCAN_STM32_TIMER_NUMBER)
19 # define TIMX_IRQn UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQn)
20 # define TIMX_INPUT_CLOCK STM32_TIMCLK1
23 # if (UAVCAN_STM32_CHIBIOS && (CH_KERNEL_MAJOR == 3 || CH_KERNEL_MAJOR == 4 || CH_KERNEL_MAJOR == 5))
24 # define TIMX UAVCAN_STM32_GLUE2(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER)
25 # define TIMX_IRQn UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _NUMBER)
26 # define TIMX_IRQHandler UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _HANDLER)
27 # define TIMX_INPUT_CLOCK STM32_TIMCLK1
29 # define TIMX_IRQHandler UAVCAN_STM32_GLUE3(TIM, UAVCAN_STM32_TIMER_NUMBER, _IRQHandler)
32 # if UAVCAN_STM32_NUTTX
33 # define TIMX UAVCAN_STM32_GLUE3(STM32_TIM, UAVCAN_STM32_TIMER_NUMBER, _BASE)
34 # define TMR_REG(o) (TIMX + (o))
35 # define TIMX_INPUT_CLOCK UAVCAN_STM32_GLUE3(STM32_APB1_TIM, UAVCAN_STM32_TIMER_NUMBER, _CLKIN)
37 # define TIMX_IRQn UAVCAN_STM32_GLUE2(STM32_IRQ_TIM, UAVCAN_STM32_TIMER_NUMBER)
40 # if UAVCAN_STM32_TIMER_NUMBER >= 2 && UAVCAN_STM32_TIMER_NUMBER <= 7
41 # if defined(STM32L4xx)
42 # define TIMX_RCC_ENR RCC->APB1ENR1
43 # define TIMX_RCC_RSTR RCC->APB1RSTR1
44 # define TIMX_RCC_ENR_MASK UAVCAN_STM32_GLUE3(RCC_APB1ENR1_TIM, UAVCAN_STM32_TIMER_NUMBER, EN)
45 # define TIMX_RCC_RSTR_MASK UAVCAN_STM32_GLUE3(RCC_APB1RSTR1_TIM, UAVCAN_STM32_TIMER_NUMBER, RST)
47 # define TIMX_RCC_ENR RCC->APB1ENR
48 # define TIMX_RCC_RSTR RCC->APB1RSTR
49 # define TIMX_RCC_ENR_MASK UAVCAN_STM32_GLUE3(RCC_APB1ENR_TIM, UAVCAN_STM32_TIMER_NUMBER, EN)
50 # define TIMX_RCC_RSTR_MASK UAVCAN_STM32_GLUE3(RCC_APB1RSTR_TIM, UAVCAN_STM32_TIMER_NUMBER, RST)
53 # error "This UAVCAN_STM32_TIMER_NUMBER is not supported yet"
68 # ifdef UAVCAN_STM32_TIMX_INPUT_CLOCK
69 # undef TIMX_INPUT_CLOCK
70 # define TIMX_INPUT_CLOCK UAVCAN_STM32_TIMX_INPUT_CLOCK
86 bool initialized =
false;
89 bool utc_locked =
false;
91 UtcSyncParams utc_sync_params;
92 float utc_prev_adj = 0;
93 float utc_rel_rate_ppm = 0;
94 float utc_rel_rate_error_integral = 0;
104 #if UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
106 static void nvicEnableVector(IRQn_Type irq,
uint8_t prio)
108 #if !defined (USE_HAL_DRIVER)
109 NVIC_InitTypeDef NVIC_InitStructure;
110 NVIC_InitStructure.NVIC_IRQChannel = irq;
111 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = prio;
112 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
113 NVIC_InitStructure.NVIC_IRQChannelCmd =
ENABLE;
114 NVIC_Init(&NVIC_InitStructure);
116 HAL_NVIC_SetPriority(irq, prio, 0);
117 HAL_NVIC_EnableIRQ(irq);
126 CriticalSectionLocker lock;
134 # if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
136 TIMX_RCC_ENR |= TIMX_RCC_ENR_MASK;
137 TIMX_RCC_RSTR |= TIMX_RCC_RSTR_MASK;
138 TIMX_RCC_RSTR &= ~TIMX_RCC_RSTR_MASK;
141 nvicEnableVector(TIMX_IRQn, UAVCAN_STM32_IRQ_PRIORITY_MASK);
143 # if (TIMX_INPUT_CLOCK % 1000000) != 0
144 # error "No way, timer clock must be divisible by 1e6. FIXME!"
149 TIMX->PSC = (TIMX_INPUT_CLOCK / 1000000) - 1;
150 TIMX->CR1 = TIM_CR1_URS;
152 TIMX->EGR = TIM_EGR_UG;
153 TIMX->DIER = TIM_DIER_UIE;
154 TIMX->CR1 = TIM_CR1_CEN;
158 # if UAVCAN_STM32_NUTTX
161 irq_attach(TIMX_IRQn, &TIMX_IRQHandler,
NULL);
164 modifyreg32(STM32_RCC_APB1ENR, 0, TIMX_RCC_ENR_MASK);
165 modifyreg32(STM32_RCC_APB1RSTR, 0, TIMX_RCC_RSTR_MASK);
166 modifyreg32(STM32_RCC_APB1RSTR, TIMX_RCC_RSTR_MASK, 0);
170 putreg32(0xFFFF, TMR_REG(STM32_BTIM_ARR_OFFSET));
171 putreg16(((TIMX_INPUT_CLOCK / 1000000)-1), TMR_REG(STM32_BTIM_PSC_OFFSET));
172 putreg16(BTIM_CR1_URS, TMR_REG(STM32_BTIM_CR1_OFFSET));
173 putreg16(0, TMR_REG(STM32_BTIM_SR_OFFSET));
174 putreg16(BTIM_EGR_UG, TMR_REG(STM32_BTIM_EGR_OFFSET));
175 putreg16(BTIM_DIER_UIE, TMR_REG(STM32_BTIM_DIER_OFFSET));
176 putreg16(BTIM_CR1_CEN, TMR_REG(STM32_BTIM_CR1_OFFSET));
182 up_enable_irq(TIMX_IRQn);
189 MutexLocker mlocker(mutex);
193 CriticalSectionLocker locker;
201 utc_rel_rate_ppm = 0;
206 # if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
213 if (TIMX->SR & TIM_SR_UIF)
217 (utc_accumulated_correction_nsec + utc_correction_nsec_per_overflow) / 1000;
223 # if UAVCAN_STM32_NUTTX
226 UAVCAN_ASSERT(getreg16(TMR_REG(STM32_BTIM_DIER_OFFSET)) & BTIM_DIER_UIE);
231 if (getreg16(TMR_REG(STM32_BTIM_SR_OFFSET)) & BTIM_SR_UIF)
233 cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET));
235 (utc_accumulated_correction_nsec + utc_correction_nsec_per_overflow) / 1000;
244 return utc_set ? sampleUtcFromCriticalSection() : 0;
252 CriticalSectionLocker locker;
256 # if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
259 if (TIMX->SR & TIM_SR_UIF)
264 # if UAVCAN_STM32_NUTTX
268 if (getreg16(TMR_REG(STM32_BTIM_SR_OFFSET)) & BTIM_SR_UIF)
270 cnt = getreg16(TMR_REG(STM32_BTIM_CNT_OFFSET));
272 time += USecPerOverflow;
293 CriticalSectionLocker locker;
294 usec = sampleUtcFromCriticalSection();
301 static float lowpass(
float xold,
float xnew,
float corner,
float dt)
303 const float tau = 1.F / corner;
304 return (dt * xnew + tau * xold) / (dt + tau);
310 const float dt = float((ts - prev_utc_adj_at).toUSec()) / 1e6F;
311 prev_utc_adj_at = ts;
312 const float adj_usec = float(adjustment.
toUSec());
318 const float target_rel_rate_ppm = adj_usec * utc_sync_params.offset_p;
324 const float new_rel_rate_ppm = (utc_prev_adj - adj_usec) / dt;
325 utc_prev_adj = adj_usec;
326 utc_rel_rate_ppm = lowpass(utc_rel_rate_ppm, new_rel_rate_ppm, utc_sync_params.rate_error_corner_freq, dt);
328 const float rel_rate_error = target_rel_rate_ppm - utc_rel_rate_ppm;
332 utc_rel_rate_error_integral = 0;
336 utc_rel_rate_error_integral += rel_rate_error * dt * utc_sync_params.rate_i;
337 utc_rel_rate_error_integral =
338 uavcan::max(utc_rel_rate_error_integral, -utc_sync_params.max_rate_correction_ppm);
339 utc_rel_rate_error_integral =
340 uavcan::min(utc_rel_rate_error_integral, utc_sync_params.max_rate_correction_ppm);
346 float total_rate_correction_ppm = rel_rate_error + utc_rel_rate_error_integral;
347 total_rate_correction_ppm =
uavcan::max(total_rate_correction_ppm, -utc_sync_params.max_rate_correction_ppm);
348 total_rate_correction_ppm =
uavcan::min(total_rate_correction_ppm, utc_sync_params.max_rate_correction_ppm);
350 utc_correction_nsec_per_overflow =
uavcan::int32_t((USecPerOverflow * 1000) * (total_rate_correction_ppm / 1e6F));
359 MutexLocker mlocker(mutex);
362 if (adjustment.
getAbs() > utc_sync_params.min_jump || !utc_set)
367 CriticalSectionLocker locker;
382 utc_rel_rate_ppm = 0;
386 updateRatePID(adjustment);
391 (std::abs(utc_rel_rate_ppm) < utc_sync_params.lock_thres_rate_ppm) &&
392 (std::abs(utc_prev_adj) < float(utc_sync_params.lock_thres_offset.toUSec()));
399 MutexLocker mlocker(mutex);
400 const float rate_correction_mult = float(utc_correction_nsec_per_overflow) / float(USecPerOverflow * 1000);
401 return 1e6F * rate_correction_mult;
406 MutexLocker mlocker(mutex);
412 MutexLocker mlocker(mutex);
418 MutexLocker mlocker(mutex);
419 return utc_sync_params;
424 MutexLocker mlocker(mutex);
426 utc_sync_params = params;
433 static union SystemClockStorage
436 long long _aligner_1;
437 long double _aligner_2;
440 SystemClock*
const ptr =
reinterpret_cast<SystemClock*
>(storage.buffer);
442 if (!clock::initialized)
444 MutexLocker mlocker(clock::mutex);
446 new (ptr)SystemClock();
463 # if UAVCAN_STM32_CHIBIOS || UAVCAN_STM32_BAREMETAL || UAVCAN_STM32_FREERTOS
466 # if UAVCAN_STM32_NUTTX
467 putreg16(0, TMR_REG(STM32_BTIM_SR_OFFSET));
473 time_mono += USecPerOverflow;
477 time_utc += USecPerOverflow;
478 utc_accumulated_correction_nsec += utc_correction_nsec_per_overflow;
479 if (std::abs(utc_accumulated_correction_nsec) >= 1000)
482 utc_accumulated_correction_nsec %= 1000;
486 if (utc_correction_nsec_per_overflow > 0)
488 utc_correction_nsec_per_overflow--;
490 else if (utc_correction_nsec_per_overflow < 0)
492 utc_correction_nsec_per_overflow++;