15
15
*/
16
16
17
17
#include "us_ticker_api.h"
18
+
19
+ #if DEVICE_USTICKER
20
+
18
21
#include "sleep_api.h"
19
22
#include "mbed_assert.h"
20
23
#include "nu_modutil.h"
@@ -60,15 +63,20 @@ static const struct nu_modinit_s timer2_modinit = {TIMER_2, TMR2_MODULE, CLK_CLK
60
63
#define TIMER_MODINIT timer2_modinit
61
64
62
65
#endif
63
-
64
- static int ticker_inited = 0 ;
66
+ /* Track ticker status */
67
+ static volatile uint16_t ticker_inited = 0 ;
65
68
66
69
#define TMR_CMP_MIN 2
67
70
#define TMR_CMP_MAX 0xFFFFFFu
68
71
69
72
void us_ticker_init (void )
70
73
{
71
74
if (ticker_inited ) {
75
+ /* By HAL spec, ticker_init allows the ticker to keep counting and disables the
76
+ * ticker interrupt. */
77
+ us_ticker_disable_interrupt ();
78
+ us_ticker_clear_interrupt ();
79
+ NVIC_ClearPendingIRQ (TIMER_MODINIT .irq_n );
72
80
return ;
73
81
}
74
82
ticker_inited = 1 ;
@@ -106,7 +114,7 @@ void us_ticker_init(void)
106
114
107
115
NVIC_SetVector (TIMER_MODINIT .irq_n , (uint32_t ) TIMER_MODINIT .var );
108
116
109
- NVIC_EnableIRQ (TIMER_MODINIT .irq_n );
117
+ NVIC_DisableIRQ (TIMER_MODINIT .irq_n );
110
118
111
119
TIMER_EnableInt (timer_base );
112
120
@@ -115,6 +123,29 @@ void us_ticker_init(void)
115
123
while (! (timer_base -> CTL & TIMER_CTL_ACTSTS_Msk ));
116
124
}
117
125
126
+ void us_ticker_free (void )
127
+ {
128
+ TIMER_T * timer_base = (TIMER_T * ) NU_MODBASE (TIMER_MODINIT .modname );
129
+
130
+ /* Stop counting */
131
+ TIMER_Stop (timer_base );
132
+
133
+ /* Wait for timer to stop counting and unset active flag */
134
+ while ((timer_base -> CTL & TIMER_CTL_ACTSTS_Msk ));
135
+
136
+ /* Disable interrupt */
137
+ TIMER_DisableInt (timer_base );
138
+ NVIC_DisableIRQ (TIMER_MODINIT .irq_n );
139
+
140
+ /* Disable IP clock
141
+ *
142
+ * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
143
+ */
144
+ CLK_DisableModuleClock_S (TIMER_MODINIT .clkidx );
145
+
146
+ ticker_inited = 0 ;
147
+ }
148
+
118
149
uint32_t us_ticker_read ()
119
150
{
120
151
if (! ticker_inited ) {
@@ -143,11 +174,15 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
143
174
uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK ;
144
175
cmp_timer = NU_CLAMP (cmp_timer , TMR_CMP_MIN , TMR_CMP_MAX );
145
176
timer_base -> CMP = cmp_timer ;
177
+
178
+ /* We can call ticker_irq_handler now. */
179
+ NVIC_EnableIRQ (TIMER_MODINIT .irq_n );
146
180
}
147
181
148
182
void us_ticker_disable_interrupt (void )
149
183
{
150
- TIMER_DisableInt ((TIMER_T * ) NU_MODBASE (TIMER_MODINIT .modname ));
184
+ /* We cannot call ticker_irq_handler now. */
185
+ NVIC_DisableIRQ (TIMER_MODINIT .irq_n );
151
186
}
152
187
153
188
void us_ticker_clear_interrupt (void )
@@ -160,6 +195,9 @@ void us_ticker_fire_interrupt(void)
160
195
// NOTE: This event was in the past. Set the interrupt as pending, but don't process it here.
161
196
// This prevents a recursive loop under heavy load which can lead to a stack overflow.
162
197
NVIC_SetPendingIRQ (TIMER_MODINIT .irq_n );
198
+
199
+ /* We can call ticker_irq_handler now. */
200
+ NVIC_EnableIRQ (TIMER_MODINIT .irq_n );
163
201
}
164
202
165
203
const ticker_info_t * us_ticker_get_info ()
@@ -177,8 +215,11 @@ static void tmr0_vec(void)
177
215
static void tmr2_vec (void )
178
216
#endif
179
217
{
180
- TIMER_ClearIntFlag ((TIMER_T * ) NU_MODBASE (TIMER_MODINIT .modname ));
181
-
218
+ us_ticker_clear_interrupt ();
219
+ us_ticker_disable_interrupt ();
220
+
182
221
// NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler();
183
222
us_ticker_irq_handler ();
184
223
}
224
+
225
+ #endif
0 commit comments