1
1
/* mbed Microcontroller Library
2
- * Copyright (c) 2006-2013 ARM Limited
2
+ * Copyright (c) 2006-2018 ARM Limited
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
#include "us_ticker_api.h"
18
18
#include "PeripheralNames.h"
19
19
#include "fsl_pit.h"
20
- #include "fsl_lptmr .h"
20
+ #include "fsl_tpm .h"
21
21
#include "fsl_clock_config.h"
22
22
23
- static int us_ticker_inited = 0 ;
24
-
25
- static void lptmr_isr (void )
23
+ const ticker_info_t * us_ticker_get_info ()
26
24
{
27
- LPTMR_ClearStatusFlags (LPTMR0 , kLPTMR_TimerCompareFlag );
28
- LPTMR_StopTimer (LPTMR0 );
25
+ static const ticker_info_t info = {
26
+ 1000000 ,
27
+ 32
28
+ };
29
+ return & info ;
30
+ }
31
+
32
+ static bool us_ticker_inited = false;
29
33
30
- us_ticker_irq_handler ();
34
+ static uint32_t us_ticker_int_counter = 0 ;
35
+ static uint16_t us_ticker_int_remainder = 0 ;
36
+
37
+ static void tpm_isr (void )
38
+ {
39
+ // Clear the TPM timer overflow flag
40
+ TPM_ClearStatusFlags (TPM2 , kTPM_TimeOverflowFlag );
41
+ TPM_StopTimer (TPM2 );
42
+
43
+ if (us_ticker_int_counter > 0 ) {
44
+ TPM2 -> MOD = 0xFFFF ;
45
+ TPM_StartTimer (TPM2 , kTPM_SystemClock );
46
+ us_ticker_int_counter -- ;
47
+ } else {
48
+ if (us_ticker_int_remainder > 0 ) {
49
+ TPM2 -> MOD = us_ticker_int_remainder ;
50
+ TPM_StartTimer (TPM2 , kTPM_SystemClock );
51
+ us_ticker_int_remainder = 0 ;
52
+ } else {
53
+ // This function is going to disable the interrupts if there are
54
+ // no other events in the queue
55
+ us_ticker_irq_handler ();
56
+ }
57
+ }
31
58
}
32
59
33
60
void us_ticker_init (void )
34
61
{
62
+ /* Common for ticker/timer. */
63
+ uint32_t busClock ;
64
+ /* Structure to initialize PIT. */
65
+ pit_config_t pitConfig ;
66
+
35
67
if (us_ticker_inited ) {
68
+ /* calling init again should cancel current interrupt */
69
+ TPM_DisableInterrupts (TPM2 , kTPM_TimeOverflowInterruptEnable );
36
70
return ;
37
71
}
38
- us_ticker_inited = 1 ;
39
-
40
- //Timer uses PIT
41
- //Common for ticker/timer
42
- uint32_t busClock ;
43
-
44
- // Structure to initialize PIT
45
- pit_config_t pitConfig ;
46
72
47
73
PIT_GetDefaultConfig (& pitConfig );
48
74
PIT_Init (PIT , & pitConfig );
@@ -55,53 +81,74 @@ void us_ticker_init(void)
55
81
PIT_StartTimer (PIT , kPIT_Chnl_0 );
56
82
PIT_StartTimer (PIT , kPIT_Chnl_1 );
57
83
58
- //Ticker uses LPTMR
59
- lptmr_config_t lptmrConfig ;
60
- LPTMR_GetDefaultConfig ( & lptmrConfig );
61
- lptmrConfig . prescalerClockSource = kLPTMR_PrescalerClock_0 ;
62
- LPTMR_Init ( LPTMR0 , & lptmrConfig );
63
-
64
- busClock = CLOCK_GetFreq ( kCLOCK_McgInternalRefClk );
65
- LPTMR_SetTimerPeriod ( LPTMR0 , busClock / 1000000 - 1 );
66
- /* Set interrupt handler */
67
- NVIC_SetVector ( LPTMR0_IRQn , ( uint32_t ) lptmr_isr );
68
- NVIC_EnableIRQ ( LPTMR0_IRQn ) ;
84
+ /* Configure interrupt generation counters and disable ticker interrupts. */
85
+ tpm_config_t tpmConfig ;
86
+
87
+ TPM_GetDefaultConfig ( & tpmConfig ) ;
88
+ /* Set to Div 32 to get 1MHz clock source for TPM */
89
+ tpmConfig . prescale = kTPM_Prescale_Divide_32 ;
90
+ TPM_Init ( TPM2 , & tpmConfig );
91
+ NVIC_SetVector ( TPM2_IRQn , ( uint32_t ) tpm_isr );
92
+ NVIC_EnableIRQ ( TPM2_IRQn );
93
+
94
+ us_ticker_inited = true ;
69
95
}
70
96
71
97
72
98
uint32_t us_ticker_read ()
73
99
{
74
- if (!us_ticker_inited ) {
75
- us_ticker_init ();
76
- }
77
-
78
100
return ~(PIT_GetCurrentTimerCount (PIT , kPIT_Chnl_1 ));
79
101
}
80
102
81
103
void us_ticker_disable_interrupt (void )
82
104
{
83
- LPTMR_DisableInterrupts ( LPTMR0 , kLPTMR_TimerInterruptEnable );
105
+ TPM_DisableInterrupts ( TPM2 , kTPM_TimeOverflowInterruptEnable );
84
106
}
85
107
86
108
void us_ticker_clear_interrupt (void )
87
109
{
88
- LPTMR_ClearStatusFlags ( LPTMR0 , kLPTMR_TimerCompareFlag );
110
+ TPM_ClearStatusFlags ( TPM2 , kTPM_TimeOverflowFlag );
89
111
}
90
112
91
113
void us_ticker_set_interrupt (timestamp_t timestamp )
92
114
{
93
- uint32_t now_us , delta_us ;
115
+ /* We get here absolute interrupt time which takes into account counter overflow.
116
+ * Since we use additional count-down timer to generate interrupt we need to calculate
117
+ * load value based on time-stamp.
118
+ */
119
+ const uint32_t now_ticks = us_ticker_read ();
120
+ uint32_t delta_ticks =
121
+ timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t )((uint64_t ) timestamp + 0xFFFFFFFF - now_ticks );
122
+
123
+ if (delta_ticks == 0 ) {
124
+ /* The requested delay is less than the minimum resolution of this counter. */
125
+ delta_ticks = 1 ;
126
+ }
127
+
128
+ us_ticker_int_counter = (uint32_t )(delta_ticks >> 16 );
129
+ us_ticker_int_remainder = (uint16_t )(0xFFFF & delta_ticks );
94
130
95
- now_us = us_ticker_read ( );
96
- delta_us = timestamp >= now_us ? timestamp - now_us : ( uint32_t )(( uint64_t ) timestamp + 0xFFFFFFFF - now_us ) ;
131
+ TPM_StopTimer ( TPM2 );
132
+ TPM2 -> CNT = 0 ;
97
133
98
- LPTMR_StopTimer (LPTMR0 );
99
- LPTMR_SetTimerPeriod (LPTMR0 , (uint32_t )delta_us );
100
- LPTMR_EnableInterrupts (LPTMR0 , kLPTMR_TimerInterruptEnable );
101
- LPTMR_StartTimer (LPTMR0 );
134
+ if (us_ticker_int_counter > 0 ) {
135
+ TPM2 -> MOD = 0xFFFF ;
136
+ us_ticker_int_counter -- ;
137
+ } else {
138
+ TPM2 -> MOD = us_ticker_int_remainder ;
139
+ us_ticker_int_remainder = 0 ;
140
+ }
141
+
142
+ /* Clear the count and set match value */
143
+ TPM_ClearStatusFlags (TPM2 , kTPM_TimeOverflowFlag );
144
+ TPM_EnableInterrupts (TPM2 , kTPM_TimeOverflowInterruptEnable );
145
+ TPM_StartTimer (TPM2 , kTPM_SystemClock );
102
146
}
103
147
104
148
void us_ticker_fire_interrupt (void )
105
149
{
106
- NVIC_SetPendingIRQ (LPTMR0_IRQn );
150
+ us_ticker_int_counter = 0 ;
151
+ us_ticker_int_remainder = 0 ;
152
+
153
+ NVIC_SetPendingIRQ (TPM2_IRQn );
107
154
}
0 commit comments