Skip to content

Commit fe627cb

Browse files
committed
[Nuvoton] Synchronize lp_ticker code to us_ticker
This is to make us_ticker/lp_ticker code consistent.
1 parent 86e194d commit fe627cb

File tree

4 files changed

+153
-48
lines changed

4 files changed

+153
-48
lines changed

targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,37 @@ static const struct nu_modinit_s timer0_modinit = {TIMER_0, TMR0_MODULE, CLK_CLK
4040

4141
#define TIMER_MODINIT timer0_modinit
4242

43-
static int ticker_inited = 0;
43+
/* S/W interrupt enable/disable
44+
*
45+
* Because H/W interrupt enable/disable (TIMER_EnableInt/TIMER_DisableInt) needs delay for lp_ticker,
46+
* we introduce S/W interrupt enable/disable to avoid blocking code. With S/W interrupt enable/disable,
47+
* H/W interrupt is always enabled after ticker_init. A S/W flag is used to tell whether or not
48+
* ticker_irq_handler is ready to call.
49+
*/
50+
51+
/* Ticker uninitialized */
52+
#define NU_TICKER_UNINIT 0
53+
/* Ticker initialized with interrupt disabled */
54+
#define NU_TICKER_INIT_INTR_DIS 1
55+
/* Ticker initialized with interrupt enabled */
56+
#define NU_TICKER_INIT_INTR_EN 2
57+
58+
/* Track ticker status */
59+
static volatile uint16_t ticker_stat = NU_TICKER_UNINIT;
4460

4561
#define TMR_CMP_MIN 2
4662
#define TMR_CMP_MAX 0xFFFFFFu
4763

4864
void us_ticker_init(void)
4965
{
50-
if (ticker_inited) {
66+
if (ticker_stat) {
5167
/* By HAL spec, ticker_init allows the ticker to keep counting and disables the
5268
* ticker interrupt. */
5369
us_ticker_disable_interrupt();
5470
us_ticker_clear_interrupt();
5571
return;
5672
}
57-
ticker_inited = 1;
73+
ticker_stat = NU_TICKER_INIT_INTR_DIS;
5874

5975
// Reset IP
6076
SYS_ResetModule(TIMER_MODINIT.rsetidx);
@@ -82,7 +98,7 @@ void us_ticker_init(void)
8298

8399
NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
84100

85-
TIMER_DisableInt(timer_base);
101+
TIMER_EnableInt(timer_base);
86102

87103
TIMER_Start(timer_base);
88104
/* Wait for timer to start counting and raise active flag */
@@ -95,6 +111,7 @@ void us_ticker_free(void)
95111

96112
/* Stop counting */
97113
TIMER_Stop(timer_base);
114+
98115
/* Wait for timer to stop counting and unset active flag */
99116
while((timer_base->CTL & TIMER_CTL_ACTSTS_Msk));
100117

@@ -105,12 +122,12 @@ void us_ticker_free(void)
105122
/* Disable IP clock */
106123
CLK_DisableModuleClock(TIMER_MODINIT.clkidx);
107124

108-
ticker_inited = 0;
125+
ticker_stat = NU_TICKER_UNINIT;
109126
}
110127

111128
uint32_t us_ticker_read()
112129
{
113-
if (! ticker_inited) {
130+
if (ticker_stat == NU_TICKER_UNINIT) {
114131
us_ticker_init();
115132
}
116133

@@ -121,6 +138,9 @@ uint32_t us_ticker_read()
121138

122139
void us_ticker_set_interrupt(timestamp_t timestamp)
123140
{
141+
/* We can call ticker_irq_handler now. */
142+
ticker_stat = NU_TICKER_INIT_INTR_EN;
143+
124144
/* In continuous mode, counter will be reset to zero with the following sequence:
125145
* 1. Stop counting
126146
* 2. Configure new CMP value
@@ -136,13 +156,12 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
136156
uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
137157
cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
138158
timer_base->CMP = cmp_timer;
139-
140-
TIMER_EnableInt(timer_base);
141159
}
142160

143161
void us_ticker_disable_interrupt(void)
144162
{
145-
TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
163+
/* We cannot call ticker_irq_handler now. */
164+
ticker_stat = NU_TICKER_INIT_INTR_DIS;
146165
}
147166

148167
void us_ticker_clear_interrupt(void)
@@ -152,6 +171,9 @@ void us_ticker_clear_interrupt(void)
152171

153172
void us_ticker_fire_interrupt(void)
154173
{
174+
/* We can call ticker_irq_handler now. */
175+
ticker_stat = NU_TICKER_INIT_INTR_EN;
176+
155177
// NOTE: This event was in the past. Set the interrupt as pending, but don't process it here.
156178
// This prevents a recursive loop under heavy load which can lead to a stack overflow.
157179
NVIC_SetPendingIRQ(TIMER_MODINIT.irq_n);
@@ -168,10 +190,15 @@ const ticker_info_t* us_ticker_get_info()
168190

169191
static void tmr0_vec(void)
170192
{
171-
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
172-
193+
/* NOTE: We need to clear interrupt flag earlier to reduce possibility of dummy interrupt.
194+
* This is because "clear interrupt flag" needs delay which isn't added here to avoid
195+
* blocking in ISR code. */
196+
us_ticker_clear_interrupt();
197+
173198
// NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler();
174-
us_ticker_irq_handler();
199+
if (ticker_stat == NU_TICKER_INIT_INTR_EN) {
200+
us_ticker_irq_handler();
201+
}
175202
}
176203

177204
#endif

targets/TARGET_NUVOTON/TARGET_M480/us_ticker.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,37 @@ static const struct nu_modinit_s timer0_modinit = {TIMER_0, TMR0_MODULE, CLK_CLK
4040

4141
#define TIMER_MODINIT timer0_modinit
4242

43-
static int ticker_inited = 0;
43+
/* S/W interrupt enable/disable
44+
*
45+
* Because H/W interrupt enable/disable (TIMER_EnableInt/TIMER_DisableInt) needs delay for lp_ticker,
46+
* we introduce S/W interrupt enable/disable to avoid blocking code. With S/W interrupt enable/disable,
47+
* H/W interrupt is always enabled after ticker_init. A S/W flag is used to tell whether or not
48+
* ticker_irq_handler is ready to call.
49+
*/
50+
51+
/* Ticker uninitialized */
52+
#define NU_TICKER_UNINIT 0
53+
/* Ticker initialized with interrupt disabled */
54+
#define NU_TICKER_INIT_INTR_DIS 1
55+
/* Ticker initialized with interrupt enabled */
56+
#define NU_TICKER_INIT_INTR_EN 2
57+
58+
/* Track ticker status */
59+
static volatile uint16_t ticker_stat = NU_TICKER_UNINIT;
4460

4561
#define TMR_CMP_MIN 2
4662
#define TMR_CMP_MAX 0xFFFFFFu
4763

4864
void us_ticker_init(void)
4965
{
50-
if (ticker_inited) {
66+
if (ticker_stat) {
5167
/* By HAL spec, ticker_init allows the ticker to keep counting and disables the
5268
* ticker interrupt. */
5369
us_ticker_disable_interrupt();
5470
us_ticker_clear_interrupt();
5571
return;
5672
}
57-
ticker_inited = 1;
73+
ticker_stat = NU_TICKER_INIT_INTR_DIS;
5874

5975
// Reset IP
6076
SYS_ResetModule(TIMER_MODINIT.rsetidx);
@@ -82,7 +98,7 @@ void us_ticker_init(void)
8298

8399
NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
84100

85-
TIMER_DisableInt(timer_base);
101+
TIMER_EnableInt(timer_base);
86102

87103
TIMER_Start(timer_base);
88104
/* Wait for timer to start counting and raise active flag */
@@ -106,12 +122,12 @@ void us_ticker_free(void)
106122
/* Disable IP clock */
107123
CLK_DisableModuleClock(TIMER_MODINIT.clkidx);
108124

109-
ticker_inited = 0;
125+
ticker_stat = NU_TICKER_UNINIT;
110126
}
111127

112128
uint32_t us_ticker_read()
113129
{
114-
if (! ticker_inited) {
130+
if (ticker_stat == NU_TICKER_UNINIT) {
115131
us_ticker_init();
116132
}
117133

@@ -122,6 +138,9 @@ uint32_t us_ticker_read()
122138

123139
void us_ticker_set_interrupt(timestamp_t timestamp)
124140
{
141+
/* We can call ticker_irq_handler now. */
142+
ticker_stat = NU_TICKER_INIT_INTR_EN;
143+
125144
/* In continuous mode, counter will be reset to zero with the following sequence:
126145
* 1. Stop counting
127146
* 2. Configure new CMP value
@@ -137,13 +156,12 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
137156
uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
138157
cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
139158
timer_base->CMP = cmp_timer;
140-
141-
TIMER_EnableInt(timer_base);
142159
}
143160

144161
void us_ticker_disable_interrupt(void)
145162
{
146-
TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
163+
/* We cannot call ticker_irq_handler now. */
164+
ticker_stat = NU_TICKER_INIT_INTR_DIS;
147165
}
148166

149167
void us_ticker_clear_interrupt(void)
@@ -153,6 +171,9 @@ void us_ticker_clear_interrupt(void)
153171

154172
void us_ticker_fire_interrupt(void)
155173
{
174+
/* We can call ticker_irq_handler now. */
175+
ticker_stat = NU_TICKER_INIT_INTR_EN;
176+
156177
// NOTE: This event was in the past. Set the interrupt as pending, but don't process it here.
157178
// This prevents a recursive loop under heavy load which can lead to a stack overflow.
158179
NVIC_SetPendingIRQ(TIMER_MODINIT.irq_n);
@@ -169,10 +190,15 @@ const ticker_info_t* us_ticker_get_info()
169190

170191
static void tmr0_vec(void)
171192
{
172-
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
173-
193+
/* NOTE: We need to clear interrupt flag earlier to reduce possibility of dummy interrupt.
194+
* This is because "clear interrupt flag" needs delay which isn't added here to avoid
195+
* blocking in ISR code. */
196+
us_ticker_clear_interrupt();
197+
174198
// NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler();
175-
us_ticker_irq_handler();
199+
if (ticker_stat == NU_TICKER_INIT_INTR_EN) {
200+
us_ticker_irq_handler();
201+
}
176202
}
177203

178204
#endif

targets/TARGET_NUVOTON/TARGET_NANO100/us_ticker.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,37 @@ static const struct nu_modinit_s timer0_modinit = {TIMER_0, TMR0_MODULE, CLK_CLK
4242

4343
#define TIMER_MODINIT timer0_modinit
4444

45-
static int ticker_inited = 0;
45+
/* S/W interrupt enable/disable
46+
*
47+
* Because H/W interrupt enable/disable (TIMER_EnableInt/TIMER_DisableInt) needs delay for lp_ticker,
48+
* we introduce S/W interrupt enable/disable to avoid blocking code. With S/W interrupt enable/disable,
49+
* H/W interrupt is always enabled after ticker_init. A S/W flag is used to tell whether or not
50+
* ticker_irq_handler is ready to call.
51+
*/
52+
53+
/* Ticker uninitialized */
54+
#define NU_TICKER_UNINIT 0
55+
/* Ticker initialized with interrupt disabled */
56+
#define NU_TICKER_INIT_INTR_DIS 1
57+
/* Ticker initialized with interrupt enabled */
58+
#define NU_TICKER_INIT_INTR_EN 2
59+
60+
/* Track ticker status */
61+
static volatile uint16_t ticker_stat = NU_TICKER_UNINIT;
4662

4763
#define TMR_CMP_MIN 2
4864
#define TMR_CMP_MAX 0xFFFFFFu
4965

5066
void us_ticker_init(void)
5167
{
52-
if (ticker_inited) {
68+
if (ticker_stat) {
5369
/* By HAL spec, ticker_init allows the ticker to keep counting and disables the
5470
* ticker interrupt. */
5571
us_ticker_disable_interrupt();
5672
us_ticker_clear_interrupt();
5773
return;
5874
}
59-
ticker_inited = 1;
75+
ticker_stat = NU_TICKER_INIT_INTR_DIS;
6076

6177
// Reset IP
6278
SYS_ResetModule(TIMER_MODINIT.rsetidx);
@@ -84,7 +100,7 @@ void us_ticker_init(void)
84100

85101
NVIC_EnableIRQ(TIMER_MODINIT.irq_n);
86102

87-
TIMER_DisableInt(timer_base);
103+
TIMER_EnableInt(timer_base);
88104

89105
TIMER_Start(timer_base);
90106
/* Wait for timer to start counting and raise active flag */
@@ -108,12 +124,12 @@ void us_ticker_free(void)
108124
/* Disable IP clock */
109125
CLK_DisableModuleClock(TIMER_MODINIT.clkidx);
110126

111-
ticker_inited = 0;
127+
ticker_stat = NU_TICKER_UNINIT;
112128
}
113129

114130
uint32_t us_ticker_read()
115131
{
116-
if (! ticker_inited) {
132+
if (ticker_stat == NU_TICKER_UNINIT) {
117133
us_ticker_init();
118134
}
119135

@@ -124,6 +140,9 @@ uint32_t us_ticker_read()
124140

125141
void us_ticker_set_interrupt(timestamp_t timestamp)
126142
{
143+
/* We can call ticker_irq_handler now. */
144+
ticker_stat = NU_TICKER_INIT_INTR_EN;
145+
127146
/* In continuous mode, counter will be reset to zero with the following sequence:
128147
* 1. Stop counting
129148
* 2. Configure new CMP value
@@ -139,13 +158,12 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
139158
uint32_t cmp_timer = timestamp * NU_TMRCLK_PER_TICK;
140159
cmp_timer = NU_CLAMP(cmp_timer, TMR_CMP_MIN, TMR_CMP_MAX);
141160
timer_base->CMPR = cmp_timer;
142-
143-
TIMER_EnableInt(timer_base);
144161
}
145162

146163
void us_ticker_disable_interrupt(void)
147164
{
148-
TIMER_DisableInt((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
165+
/* We cannot call ticker_irq_handler now. */
166+
ticker_stat = NU_TICKER_INIT_INTR_DIS;
149167
}
150168

151169
void us_ticker_clear_interrupt(void)
@@ -155,6 +173,9 @@ void us_ticker_clear_interrupt(void)
155173

156174
void us_ticker_fire_interrupt(void)
157175
{
176+
/* We can call ticker_irq_handler now. */
177+
ticker_stat = NU_TICKER_INIT_INTR_EN;
178+
158179
// NOTE: This event was in the past. Set the interrupt as pending, but don't process it here.
159180
// This prevents a recursive loop under heavy load which can lead to a stack overflow.
160181
NVIC_SetPendingIRQ(TIMER_MODINIT.irq_n);
@@ -171,10 +192,15 @@ const ticker_info_t* us_ticker_get_info()
171192

172193
void TMR0_IRQHandler(void)
173194
{
174-
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname));
175-
195+
/* NOTE: We need to clear interrupt flag earlier to reduce possibility of dummy interrupt.
196+
* This is because "clear interrupt flag" needs delay which isn't added here to avoid
197+
* blocking in ISR code. */
198+
us_ticker_clear_interrupt();
199+
176200
// NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler();
177-
us_ticker_irq_handler();
201+
if (ticker_stat == NU_TICKER_INIT_INTR_EN) {
202+
us_ticker_irq_handler();
203+
}
178204
}
179205

180206
#endif

0 commit comments

Comments
 (0)