10 #if UAVCAN_KINETIS_TIMER_NUMBER
18 # define TIMX_IRQHandler UAVCAN_KINETIS_GLUE3(PIT, UAVCAN_KINETIS_TIMER_NUMBER, _IRQHandler)
19 # define TIMX (KINETIS_PIT_BASE + (UAVCAN_KINETIS_TIMER_NUMBER << 4))
20 # define TMR_REG(o) (TIMX + (o))
21 # define TIMX_INPUT_CLOCK BOARD_BUS_FREQ
22 # define TIMX_INTERRUPT_FREQ 16
23 # define TIMX_IRQn UAVCAN_KINETIS_GLUE2(KINETIS_IRQ_PITCH, UAVCAN_KINETIS_TIMER_NUMBER)
25 # if UAVCAN_KINETIS_TIMER_NUMBER >= 0 && UAVCAN_KINETIS_TIMER_NUMBER <= 3
26 # define KINETIS_PIT_LDVAL_OFFSET KINETIS_PIT_LDVAL0_OFFSET
27 # define KINETIS_PIT_CVAL_OFFSET KINETIS_PIT_CVAL0_OFFSET
28 # define KINETIS_PIT_TCTRL_OFFSET KINETIS_PIT_TCTRL0_OFFSET
29 # define KINETIS_PIT_TFLG_OFFSET KINETIS_PIT_TFLG0_OFFSET
31 # error "This UAVCAN_KINETIS_TIMER_NUMBER is not supported yet"
43 const uavcan::uint32_t CountsPerPeriod = (TIMX_INPUT_CLOCK / TIMX_INTERRUPT_FREQ);
49 bool initialized =
false;
52 bool utc_locked =
false;
54 UtcSyncParams utc_sync_params;
55 float utc_prev_adj = 0;
56 float utc_rel_rate_ppm = 0;
57 float utc_rel_rate_error_integral = 0;
69 CriticalSectionLocker lock;
77 irq_attach(TIMX_IRQn, &TIMX_IRQHandler,
NULL);
80 modifyreg32(KINETIS_SIM_SCGC6, 0, SIM_SCGC6_PIT);
83 putreg32(0, KINETIS_PIT_MCR);
87 putreg32(CountsPerPeriod - 1, TMR_REG(KINETIS_PIT_LDVAL_OFFSET));
88 putreg32(PIT_TCTRL_TEN | PIT_TCTRL_TIE, TMR_REG(KINETIS_PIT_TCTRL_OFFSET));
98 up_prioritize_irq(TIMX_IRQn, NVIC_SYSH_HIGH_PRIORITY);
100 up_enable_irq(TIMX_IRQn);
105 MutexLocker mlocker(mutex);
109 CriticalSectionLocker locker;
117 utc_rel_rate_ppm = 0;
123 UAVCAN_ASSERT(getreg32(TMR_REG(KINETIS_PIT_TCTRL_OFFSET)) & PIT_TCTRL_TIE);
126 volatile uavcan::uint32_t cnt = CountsPerPeriod - getreg32(TMR_REG(KINETIS_PIT_CVAL_OFFSET));
128 if (getreg32(TMR_REG(KINETIS_PIT_TFLG_OFFSET)) & PIT_TFLG_TIF)
130 cnt = CountsPerPeriod - getreg32(TMR_REG(KINETIS_PIT_CVAL_OFFSET));
132 (utc_accumulated_correction_nsec + utc_correction_nsec_per_overflow) / 1000;
135 return time + (cnt / CountsPerUs);
140 return utc_set ? sampleUtcFromCriticalSection() : 0;
148 CriticalSectionLocker locker;
151 volatile uavcan::uint32_t cnt = CountsPerPeriod - getreg32(TMR_REG(KINETIS_PIT_CVAL_OFFSET));
153 if (getreg32(TMR_REG(KINETIS_PIT_TFLG_OFFSET)) & PIT_TFLG_TIF)
155 cnt = CountsPerPeriod - getreg32(TMR_REG(KINETIS_PIT_CVAL_OFFSET));
156 time += USecPerOverflow;
158 usec = time + (cnt / CountsPerUs);
172 CriticalSectionLocker locker;
173 usec = sampleUtcFromCriticalSection();
180 static float lowpass(
float xold,
float xnew,
float corner,
float dt)
182 const float tau = 1.F / corner;
183 return (dt * xnew + tau * xold) / (dt + tau);
189 const float dt = float((ts - prev_utc_adj_at).toUSec()) / 1e6F;
190 prev_utc_adj_at = ts;
191 const float adj_usec = float(adjustment.
toUSec());
197 const float target_rel_rate_ppm = adj_usec * utc_sync_params.offset_p;
203 const float new_rel_rate_ppm = (utc_prev_adj - adj_usec) / dt;
204 utc_prev_adj = adj_usec;
205 utc_rel_rate_ppm = lowpass(utc_rel_rate_ppm, new_rel_rate_ppm, utc_sync_params.rate_error_corner_freq, dt);
207 const float rel_rate_error = target_rel_rate_ppm - utc_rel_rate_ppm;
211 utc_rel_rate_error_integral = 0;
215 utc_rel_rate_error_integral += rel_rate_error * dt * utc_sync_params.rate_i;
216 utc_rel_rate_error_integral =
217 uavcan::max(utc_rel_rate_error_integral, -utc_sync_params.max_rate_correction_ppm);
218 utc_rel_rate_error_integral =
219 uavcan::min(utc_rel_rate_error_integral, utc_sync_params.max_rate_correction_ppm);
225 float total_rate_correction_ppm = rel_rate_error + utc_rel_rate_error_integral;
226 total_rate_correction_ppm =
uavcan::max(total_rate_correction_ppm, -utc_sync_params.max_rate_correction_ppm);
227 total_rate_correction_ppm =
uavcan::min(total_rate_correction_ppm, utc_sync_params.max_rate_correction_ppm);
229 utc_correction_nsec_per_overflow =
uavcan::int32_t((USecPerOverflow * 1000) * (total_rate_correction_ppm / 1e6F));
238 MutexLocker mlocker(mutex);
241 if (adjustment.
getAbs() > utc_sync_params.min_jump || !utc_set)
246 CriticalSectionLocker locker;
261 utc_rel_rate_ppm = 0;
265 updateRatePID(adjustment);
270 (std::abs(utc_rel_rate_ppm) < utc_sync_params.lock_thres_rate_ppm) &&
271 (std::abs(utc_prev_adj) < float(utc_sync_params.lock_thres_offset.toUSec()));
278 MutexLocker mlocker(mutex);
279 const float rate_correction_mult = float(utc_correction_nsec_per_overflow) / float(USecPerOverflow * 1000);
280 return 1e6F * rate_correction_mult;
285 MutexLocker mlocker(mutex);
291 MutexLocker mlocker(mutex);
297 MutexLocker mlocker(mutex);
298 return utc_sync_params;
303 MutexLocker mlocker(mutex);
305 utc_sync_params = params;
312 static union SystemClockStorage
315 long long _aligner_1;
316 long double _aligner_2;
321 if (!clock::initialized)
323 MutexLocker mlocker(clock::mutex);
340 putreg32(PIT_TFLG_TIF, TMR_REG(KINETIS_PIT_TFLG_OFFSET));
345 time_mono += USecPerOverflow;
349 time_utc += USecPerOverflow;
350 utc_accumulated_correction_nsec += utc_correction_nsec_per_overflow;
351 if (std::abs(utc_accumulated_correction_nsec) >= 1000)
354 utc_accumulated_correction_nsec %= 1000;
358 if (utc_correction_nsec_per_overflow > 0)
360 utc_correction_nsec_per_overflow--;
362 else if (utc_correction_nsec_per_overflow < 0)
364 utc_correction_nsec_per_overflow++;