rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
hal_gpt_lld.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2014 Derek Mulcahy
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file PITv1/hal_gpt_lld.c
19 * @brief KINETIS GPT subsystem low level driver source.
20 * @author andreika <prometheus.pcb@gmail.com>
21 *
22 * @addtogroup GPT
23 * @{
24 */
25
26#include "hal.h"
27
28#if HAL_USE_GPT || defined(__DOXYGEN__)
29
30/*===========================================================================*/
31/* Driver local definitions. */
32/*===========================================================================*/
33
34/*===========================================================================*/
35/* Driver exported variables. */
36/*===========================================================================*/
37
38/**
39 * @brief GPTD1 driver identifier.
40 * @note The driver GPTD1 allocates the complex timer PIT0 when enabled.
41 */
42#if KINETIS_GPT_USE_PIT0 || defined(__DOXYGEN__)
44#endif
45
46/**
47 * @brief GPTD2 driver identifier.
48 * @note The driver GPTD2 allocates the timer PIT1 when enabled.
49 */
50#if KINETIS_GPT_USE_PIT1 || defined(__DOXYGEN__)
52#endif
53
54/**
55 * @brief GPTD3 driver identifier.
56 * @note The driver GPTD3 allocates the timer PIT2 when enabled.
57 */
58#if KINETIS_GPT_USE_PIT2 || defined(__DOXYGEN__)
60#endif
61
62/**
63 * @brief GPTD4 driver identifier.
64 * @note The driver GPTD4 allocates the timer PIT3 when enabled.
65 */
66#if KINETIS_GPT_USE_PIT3 || defined(__DOXYGEN__)
68#endif
69
70/*===========================================================================*/
71/* Driver local variables and types. */
72/*===========================================================================*/
73
74#if KINETIS_HAS_PIT_COMMON_IRQ
75static uint8_t active_channels = 0;
76#endif /* KINETIS_HAS_PIT_COMMON_IRQ */
77
78#ifdef KE1xF
79static const uint32_t tif_flags[] = { LPIT_MSR_TIF0(1), LPIT_MSR_TIF1(1), LPIT_MSR_TIF2(1), LPIT_MSR_TIF3(1) };
80static const uint32_t mier_flags[] = { LPIT_MIER_TIE0(1), LPIT_MIER_TIE1(1), LPIT_MIER_TIE2(1), LPIT_MIER_TIE3(1) };
81#endif
82
83/*===========================================================================*/
84/* Driver local functions. */
85/*===========================================================================*/
86
87/**
88 * @brief Shared IRQ handler.
89 *
90 * @param[in] gptp pointer to a @p GPTDriver object
91 */
93
94 /* Clear the interrupt */
95#ifdef KE1xF
96 PIT->MSR |= tif_flags[gptp->channelIndex];
97#else
98 gptp->channel->TFLG |= PIT_TFLGn_TIF;
99#endif
100
101 if (gptp->state == GPT_ONESHOT) {
102 gptp->state = GPT_READY; /* Back in GPT_READY state. */
103 gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */
104 }
105 gptp->config->callback(gptp);
106}
107
108/*===========================================================================*/
109/* Driver interrupt handlers. */
110/*===========================================================================*/
111
112#if !KINETIS_HAS_PIT_COMMON_IRQ
113
114#if KINETIS_GPT_USE_PIT0
115/**
116 * @brief PIT1 interrupt handler.
117 *
118 * @isr
119 */
120OSAL_IRQ_HANDLER(KINETIS_PIT0_IRQ_VECTOR) {
121 OSAL_IRQ_PROLOGUE();
123 OSAL_IRQ_EPILOGUE();
124}
125#endif /* KINETIS_GPT_USE_PIT0 */
126
127#if KINETIS_GPT_USE_PIT1
128/**
129 * @brief PIT1 interrupt handler.
130 *
131 * @isr
132 */
133OSAL_IRQ_HANDLER(KINETIS_PIT1_IRQ_VECTOR) {
134 OSAL_IRQ_PROLOGUE();
136 OSAL_IRQ_EPILOGUE();
137}
138#endif /* KINETIS_GPT_USE_PIT1 */
139
140#if KINETIS_GPT_USE_PIT2
141/**
142 * @brief PIT2 interrupt handler.
143 *
144 * @isr
145 */
146OSAL_IRQ_HANDLER(KINETIS_PIT2_IRQ_VECTOR) {
147 OSAL_IRQ_PROLOGUE();
149 OSAL_IRQ_EPILOGUE();
150}
151#endif /* KINETIS_GPT_USE_PIT2 */
152
153#if KINETIS_GPT_USE_PIT3
154/**
155 * @brief PIT3 interrupt handler.
156 *
157 * @isr
158 */
159OSAL_IRQ_HANDLER(KINETIS_PIT3_IRQ_VECTOR) {
160 OSAL_IRQ_PROLOGUE();
162 OSAL_IRQ_EPILOGUE();
163}
164#endif /* KINETIS_GPT_USE_PIT3 */
165
166#else /* !KINETIS_HAS_PIT_COMMON_IRQ */
167/**
168 * @brief Common PIT interrupt handler.
169 *
170 * @isr
171 */
172OSAL_IRQ_HANDLER(KINETIS_PIT_IRQ_VECTOR) {
173 OSAL_IRQ_PROLOGUE();
174#if KINETIS_GPT_USE_PIT0
175#ifdef KE1xF
176 if(PIT->MSR & LPIT_MSR_TIF0(1))
177#else
178 if(GPTD1.channel->TFLG & PIT_TFLGn_TIF)
179#endif
181#endif /* KINETIS_GPT_USE_PIT0 */
182#if KINETIS_GPT_USE_PIT1
183#ifdef KE1xF
184 if(PIT->MSR & LPIT_MSR_TIF1(1))
185#else
186 if(GPTD2.channel->TFLG & PIT_TFLGn_TIF)
187#endif
189#endif /* KINETIS_GPT_USE_PIT1 */
190#if KINETIS_GPT_USE_PIT2
191#ifdef KE1xF
192 if(PIT->MSR & LPIT_MSR_TIF2(1))
193#else
194 if(GPTD3.channel->TFLG & PIT_TFLGn_TIF)
195#endif
197#endif /* KINETIS_GPT_USE_PIT2 */
198#if KINETIS_GPT_USE_PIT3
199#ifdef KE1xF
200 if(PIT->MSR & LPIT_MSR_TIF3(1))
201#else
202 if(GPTD4.channel->TFLG & PIT_TFLGn_TIF)
203#endif
205#endif /* KINETIS_GPT_USE_PIT3 */
206 OSAL_IRQ_EPILOGUE();
207}
208
209#endif /* !KINETIS_HAS_PIT_COMMON_IRQ */
210
211/*===========================================================================*/
212/* Driver exported functions. */
213/*===========================================================================*/
214
215/**
216 * @brief Low level GPT driver initialization.
217 *
218 * @notapi
219 */
220void gpt_lld_init(void) {
221
222#if KINETIS_GPT_USE_PIT0
223 /* Driver initialization.*/
224#ifdef KE1xF
226#else
227 GPTD1.channel = &PIT->CHANNEL[0];
228#endif
229 gptObjectInit(&GPTD1);
230#endif
231
232#if KINETIS_GPT_USE_PIT1
233 /* Driver initialization.*/
234#ifdef KE1xF
236#else
237 GPTD2.channel = &PIT->CHANNEL[1];
238#endif
239 gptObjectInit(&GPTD2);
240#endif
241
242#if KINETIS_GPT_USE_PIT2
243 /* Driver initialization.*/
244#ifdef KE1xF
246#else
247 GPTD3.channel = &PIT->CHANNEL[2];
248#endif
249 gptObjectInit(&GPTD3);
250#endif
251
252#if KINETIS_GPT_USE_PIT3
253 /* Driver initialization.*/
254#ifdef KE1xF
256#else
257 GPTD4.channel = &PIT->CHANNEL[3];
258#endif
259 gptObjectInit(&GPTD4);
260#endif
261}
262
263/**
264 * @brief Configures and activates the GPT peripheral.
265 *
266 * @param[in] gptp pointer to the @p GPTDriver object
267 *
268 * @notapi
269 */
271 uint16_t psc;
272
273 if (gptp->state == GPT_STOP) {
274#ifdef KE1xF
275 /* Clock activation.*/
276 PCC->CLKCFG[PCC_LPIT0_INDEX] |= PCC_CLKCFG_CGC(1);
277 //SCG->FIRCDIV = SCG_FIRCDIV_FIRCDIV2(1) | SCG_FIRCDIV_FIRCDIV1(1);
278 PCC->CLKCFG[PCC_LPIT0_INDEX] = (PCC->CLKCFG[PCC_LPIT0_INDEX] & ~PCC_CLKCFG_PCS_MASK) | PCC_CLKCFG_PCS(6/*SCGPCLK System PLL clock*/);
279#else
280 /* Clock activation.*/
281 SIM->SCGC6 |= SIM_SCGC6_PIT;
282#endif
283 gptp->clock = KINETIS_SPLL_DIV2_FREQENCY/*KINETIS_SYSCLK_FREQUENCY*/;
284
285#if !KINETIS_HAS_PIT_COMMON_IRQ
286
287#if KINETIS_GPT_USE_PIT0
288 if (&GPTD1 == gptp) {
289 nvicEnableVector(PITChannel0_IRQn, KINETIS_GPT_PIT0_IRQ_PRIORITY);
290 }
291#endif
292#if KINETIS_GPT_USE_PIT1
293 if (&GPTD2 == gptp) {
294 nvicEnableVector(PITChannel1_IRQn, KINETIS_GPT_PIT1_IRQ_PRIORITY);
295 }
296#endif
297#if KINETIS_GPT_USE_PIT2
298 if (&GPTD3 == gptp) {
299 nvicEnableVector(PITChannel2_IRQn, KINETIS_GPT_PIT2_IRQ_PRIORITY);
300 }
301#endif
302#if KINETIS_GPT_USE_PIT3
303 if (&GPTD4 == gptp) {
304 nvicEnableVector(PITChannel3_IRQn, KINETIS_GPT_PIT3_IRQ_PRIORITY);
305 }
306#endif
307
308#else /* !KINETIS_HAS_PIT_COMMON_IRQ */
309 nvicEnableVector(PIT_IRQn, KINETIS_GPT_PIT_IRQ_PRIORITY);
311#endif /* !KINETIS_HAS_PIT_COMMON_IRQ */
312 }
313
314 /* Prescaler value calculation.*/
315 psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1);
316 osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock,
317 "invalid frequency");
318
319#ifdef KE1xF
320 /* Enable the PIT */
321 PIT->MCR |= LPIT_MCR_M_CEN(1);
322#else
323 /* Enable the PIT */
324 PIT->MCR = 0;
325#endif
326}
327
328/**
329 * @brief Deactivates the GPT peripheral.
330 *
331 * @param[in] gptp pointer to the @p GPTDriver object
332 *
333 * @notapi
334 */
336
337 if (gptp->state == GPT_READY) {
338#ifdef KE1xF
339 PCC->CLKCFG[PCC_LPIT0_INDEX] &= ~PCC_CLKCFG_CGC(1);
340
341 /* Disable the channel */
342 PIT->CHANNEL[gptp->channelIndex].TCTRL = 0;
343
344 /* Disable interrupts */
345 PIT->MIER &= ~mier_flags[gptp->channelIndex];
346
347 /* Clear pending interrupts */
348 PIT->MSR |= tif_flags[gptp->channelIndex];
349#else
350 SIM->SCGC6 &= ~SIM_SCGC6_PIT;
351
352 /* Disable the channel */
353 gptp->channel->TCTRL = 0;
354
355 /* Clear pending interrupts */
356 gptp->channel->TFLG |= PIT_TFLGn_TIF;
357#endif
358
359#if !KINETIS_HAS_PIT_COMMON_IRQ
360
361#if KINETIS_GPT_USE_PIT0
362 if (&GPTD1 == gptp) {
363 nvicDisableVector(PITChannel0_IRQn);
364 }
365#endif
366#if KINETIS_GPT_USE_PIT1
367 if (&GPTD2 == gptp) {
368 nvicDisableVector(PITChannel1_IRQn);
369 }
370#endif
371#if KINETIS_GPT_USE_PIT2
372 if (&GPTD3 == gptp) {
373 nvicDisableVector(PITChannel2_IRQn);
374 }
375#endif
376#if KINETIS_GPT_USE_PIT3
377 if (&GPTD4 == gptp) {
378 nvicDisableVector(PITChannel3_IRQn);
379 }
380#endif
381
382#else /* !KINETIS_HAS_PIT_COMMON_IRQ */
383 if(--active_channels == 0)
384 nvicDisableVector(PIT_IRQn);
385#endif /* !KINETIS_HAS_PIT_COMMON_IRQ */
386 }
387}
388
389/**
390 * @brief Starts the timer in continuous mode.
391 *
392 * @param[in] gptp pointer to the @p GPTDriver object
393 * @param[in] interval period in ticks
394 *
395 * @notapi
396 */
398#ifdef KE1xF
399 /* Clear pending interrupts */
400 PIT->MSR |= tif_flags[gptp->channelIndex];
401
402 /* Set the interval */
403 gpt_lld_change_interval(gptp, interval);
404
405 /* Enable interrupts */
406 PIT->MIER |= mier_flags[gptp->channelIndex];
407 /* Start the timer */
408 PIT->CHANNEL[gptp->channelIndex].TCTRL |= LPIT_TCTRL_T_EN(1);
409#else
410 /* Clear pending interrupts */
411 gptp->channel->TFLG |= PIT_TFLGn_TIF;
412
413 /* Set the interval */
414 gpt_lld_change_interval(gptp, interval);
415
416 /* Start the timer */
417 gptp->channel->TCTRL |= PIT_TCTRLn_TIE | PIT_TCTRLn_TEN;
418#endif
419}
420
421/**
422 * @brief Stops the timer.
423 *
424 * @param[in] gptp pointer to the @p GPTDriver object
425 *
426 * @notapi
427 */
429#ifdef KE1xF
430 /* Stop the timer */
431 PIT->CHANNEL[gptp->channelIndex].TCTRL = 0;
432#else
433 /* Stop the timer */
434 gptp->channel->TCTRL = 0;
435#endif
436}
437
438/**
439 * @brief Starts the timer in one shot mode and waits for completion.
440 * @details This function specifically polls the timer waiting for completion
441 * in order to not have extra delays caused by interrupt servicing,
442 * this function is only recommended for short delays.
443 *
444 * @param[in] gptp pointer to the @p GPTDriver object
445 * @param[in] interval time interval in ticks
446 *
447 * @notapi
448 */
450#ifdef KE1xF
451 /* Disable timer and disable interrupts */
452 PIT->CHANNEL[gptp->channelIndex].TCTRL = 0;
453
454 PIT->MSR |= tif_flags[gptp->channelIndex];
455
456 /* Set the interval */
457 PIT->CHANNEL[gptp->channelIndex].TVAL = (gptp->clock / gptp->config->frequency) * interval;
458
459 PIT->CHANNEL[gptp->channelIndex].TCTRL = LPIT_TCTRL_T_EN(1);
460
461 while (!(PIT->MSR & tif_flags[gptp->channelIndex]))
462 ;
463 /* Disable timer and disable interrupts */
464 PIT->CHANNEL[gptp->channelIndex].TCTRL = 0;
465#else
466 struct PIT_CHANNEL *channel = gptp->channel;
467
468 /* Disable timer and disable interrupts */
469 channel->TCTRL = 0;
470
471 /* Clear the interrupt flag */
472 channel->TFLG |= PIT_TFLGn_TIF;
473
474 /* Set the interval */
475 channel->LDVAL = (gptp->clock / gptp->config->frequency) * interval;
476
477 /* Enable Timer but keep interrupts disabled */
478 channel->TCTRL = PIT_TCTRLn_TEN;
479
480 /* Wait for the interrupt flag to be set */
481 while (!(channel->TFLG & PIT_TFLGn_TIF))
482 ;
483 /* Disable timer and disable interrupts */
484 channel->TCTRL = 0;
485#endif
486}
487
488#endif /* HAL_USE_GPT */
489
490/** @} */
uint16_t channel
Definition adc_inputs.h:104
void gpt_lld_start(GPTDriver *gptp)
Configures and activates the GPT peripheral.
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval)
Starts the timer in one shot mode and waits for completion.
static void gpt_lld_serve_interrupt(GPTDriver *gptp)
Shared IRQ handler.
Definition hal_gpt_lld.c:92
void gpt_lld_stop(GPTDriver *gptp)
Deactivates the GPT peripheral.
static const uint32_t mier_flags[]
Definition hal_gpt_lld.c:80
struct PIT_CHANNEL * channel
Channel structure in PIT registers block.
GPTDriver GPTD1
GPTD1 driver identifier.
Definition hal_gpt_lld.c:43
static uint8_t active_channels
Definition hal_gpt_lld.c:75
GPTDriver GPTD3
GPTD3 driver identifier.
Definition hal_gpt_lld.c:59
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval)
Starts the timer in continuous mode.
GPTDriver GPTD2
GPTD2 driver identifier.
Definition hal_gpt_lld.c:51
OSAL_IRQ_HANDLER(KINETIS_PIT0_IRQ_VECTOR)
PIT1 interrupt handler.
const GPTConfig * config
Current configuration data.
uint32_t gptcnt_t
GPT counter type.
gptfreq_t frequency
Timer clock in Hz.
GPTDriver GPTD4
GPTD4 driver identifier.
Definition hal_gpt_lld.c:67
static const uint32_t tif_flags[]
Definition hal_gpt_lld.c:79
void gpt_lld_stop_timer(GPTDriver *gptp)
Stops the timer.
gptstate_t state
Driver state.
void gpt_lld_init(void)
Low level GPT driver initialization.
GPT_DRIVER_EXT_FIELDS uint32_t clock
Timer base clock.
gptcallback_t callback
Timer callback pointer.
int32_t channelIndex
Channel index.
Structure representing a GPT driver.