Skip to content

Commit e4332af

Browse files
committed
[MAX32600MBED,MAXWSNENV] Added low-power ticker.
1 parent 16156f5 commit e4332af

File tree

8 files changed

+178
-198
lines changed

8 files changed

+178
-198
lines changed

libraries/mbed/targets/hal/TARGET_Maxim/TARGET_MAX32600/device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464

6565
#define DEVICE_ERROR_PATTERN 1
6666

67+
#define DEVICE_LOWPOWERTIMER 1
68+
6769
#define DEVICE_CAN 0
6870
#define DEVICE_ETHERNET 0
6971

libraries/mbed/targets/hal/TARGET_Maxim/TARGET_MAX32600/rtc_api.c

Lines changed: 78 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -32,56 +32,51 @@
3232
*/
3333

3434
#include "rtc_api.h"
35+
#include "lp_ticker_api.h"
3536
#include "cmsis.h"
3637
#include "rtc_regs.h"
3738
#include "pwrseq_regs.h"
3839
#include "clkman_regs.h"
3940

41+
#define PRESCALE_VAL MXC_E_RTC_PRESCALE_DIV_2_0 // Set the divider for the 4kHz clock
42+
#define SHIFT_AMT (MXC_E_RTC_PRESCALE_DIV_2_12 - PRESCALE_VAL)
43+
4044
static int rtc_inited = 0;
4145
static volatile uint32_t overflow_cnt = 0;
42-
static uint32_t overflow_alarm = 0;
46+
47+
static uint64_t rtc_read64(void);
4348

4449
//******************************************************************************
4550
static void overflow_handler(void)
4651
{
47-
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
52+
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_OVERFLOW;
4853
overflow_cnt++;
49-
50-
if (overflow_cnt == overflow_alarm) {
51-
// Enable the comparator interrupt for the alarm
52-
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
53-
}
54-
}
55-
56-
//******************************************************************************
57-
static void alarm_handler(void)
58-
{
59-
MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
60-
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
6154
}
6255

6356
//******************************************************************************
6457
void rtc_init(void)
6558
{
66-
if(rtc_inited) {
59+
if (rtc_inited) {
6760
return;
6861
}
6962
rtc_inited = 1;
7063

64+
overflow_cnt = 0;
65+
7166
// Enable the clock to the synchronizer
7267
MXC_CLKMAN->clk_ctrl_13_rtc_int_sync = MXC_E_CLKMAN_CLK_SCALE_ENABLED;
7368

7469
// Enable the clock to the RTC
7570
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN;
7671

77-
// Set the divider from the 4kHz clock
78-
MXC_RTCTMR->prescale = MXC_E_RTC_PRESCALE_DIV_2_0;
72+
// Set the clock divider
73+
MXC_RTCTMR->prescale = PRESCALE_VAL;
7974

8075
// Enable the overflow interrupt
8176
MXC_RTCTMR->inten |= MXC_F_RTC_FLAGS_OVERFLOW;
8277

8378
// Prepare interrupt handlers
84-
NVIC_SetVector(RTC0_IRQn, (uint32_t)alarm_handler);
79+
NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
8580
NVIC_EnableIRQ(RTC0_IRQn);
8681
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
8782
NVIC_EnableIRQ(RTC3_IRQn);
@@ -90,6 +85,12 @@ void rtc_init(void)
9085
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE;
9186
}
9287

88+
//******************************************************************************
89+
void lp_ticker_init(void)
90+
{
91+
rtc_init();
92+
}
93+
9394
//******************************************************************************
9495
void rtc_free(void)
9596
{
@@ -118,73 +119,104 @@ int rtc_isenabled(void)
118119
//******************************************************************************
119120
time_t rtc_read(void)
120121
{
121-
unsigned int shift_amt;
122122
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
123-
124-
// Account for a change in the default prescaler
125-
shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
123+
uint32_t ovf1, ovf2;
126124

127125
// Ensure coherency between overflow_cnt and timer
128126
do {
129127
ovf_cnt_1 = overflow_cnt;
128+
ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
130129
timer_cnt = MXC_RTCTMR->timer;
130+
ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
131131
ovf_cnt_2 = overflow_cnt;
132-
} while (ovf_cnt_1 != ovf_cnt_2);
132+
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
133133

134-
return (timer_cnt >> shift_amt) + (ovf_cnt_1 << (32 - shift_amt));
134+
// Account for an unserviced interrupt
135+
if (ovf1) {
136+
ovf_cnt_1++;
137+
}
138+
139+
return (timer_cnt >> SHIFT_AMT) + (ovf_cnt_1 << (32 - SHIFT_AMT));
135140
}
136141

137142
//******************************************************************************
138-
uint64_t rtc_read_us(void)
143+
static uint64_t rtc_read64(void)
139144
{
140-
unsigned int shift_amt;
141145
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
142-
uint64_t currentUs;
143-
144-
// Account for a change in the default prescaler
145-
shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
146+
uint32_t ovf1, ovf2;
147+
uint64_t current_us;
146148

147149
// Ensure coherency between overflow_cnt and timer
148150
do {
149151
ovf_cnt_1 = overflow_cnt;
152+
ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
150153
timer_cnt = MXC_RTCTMR->timer;
154+
ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
151155
ovf_cnt_2 = overflow_cnt;
152-
} while (ovf_cnt_1 != ovf_cnt_2);
156+
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
153157

154-
currentUs = (((uint64_t)timer_cnt * 1000000) >> shift_amt) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - shift_amt));
158+
// Account for an unserviced interrupt
159+
if (ovf1) {
160+
ovf_cnt_1++;
161+
}
162+
163+
current_us = (((uint64_t)timer_cnt * 1000000) >> SHIFT_AMT) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - SHIFT_AMT));
155164

156-
return currentUs;
165+
return current_us;
157166
}
158167

159168
//******************************************************************************
160169
void rtc_write(time_t t)
161170
{
162-
// Account for a change in the default prescaler
163-
unsigned int shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
164-
165171
MXC_RTCTMR->ctrl &= ~MXC_F_RTC_CTRL_ENABLE; // disable the timer while updating
166-
MXC_RTCTMR->timer = t << shift_amt;
167-
overflow_cnt = t >> (32 - shift_amt);
172+
MXC_RTCTMR->timer = t << SHIFT_AMT;
173+
overflow_cnt = t >> (32 - SHIFT_AMT);
168174
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; // enable the timer while updating
169175
}
170176

171177
//******************************************************************************
172-
void rtc_set_wakeup(uint64_t wakeupUs)
178+
void lp_ticker_set_interrupt(timestamp_t timestamp)
173179
{
174-
// Account for a change in the default prescaler
175-
unsigned int shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
180+
// Note: interrupts are disabled before this function is called.
176181

177182
// Disable the alarm while it is prepared
178183
MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
179184
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; // clear interrupt
180185

181-
overflow_alarm = (wakeupUs >> (32 - shift_amt)) / 1000000;
182-
183-
if (overflow_alarm == overflow_cnt) {
184-
MXC_RTCTMR->comp[0] = (wakeupUs << shift_amt) / 1000000;
185-
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
186+
uint64_t curr_ts64 = rtc_read64();
187+
uint64_t ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL);
188+
if (ts64 < curr_ts64) {
189+
if (ts64 < (curr_ts64 - 1000)) {
190+
ts64 += 0x100000000ULL;
191+
} else {
192+
// This event has already occurred. Set the alarm to expire immediately.
193+
MXC_RTCTMR->comp[0] = MXC_RTCTMR->timer + 2;
194+
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
195+
return;
196+
}
186197
}
187198

199+
MXC_RTCTMR->comp[0] = (ts64 << SHIFT_AMT) / 1000000;
200+
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
201+
188202
// Enable wakeup from RTC
189203
MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER | MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0);
190204
}
205+
206+
//******************************************************************************
207+
inline void lp_ticker_disable_interrupt(void)
208+
{
209+
MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
210+
}
211+
212+
//******************************************************************************
213+
inline void lp_ticker_clear_interrupt(void)
214+
{
215+
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
216+
}
217+
218+
//******************************************************************************
219+
inline uint32_t lp_ticker_read(void)
220+
{
221+
return rtc_read64();
222+
}

libraries/mbed/targets/hal/TARGET_Maxim/TARGET_MAX32600/sleep.c

Lines changed: 3 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,14 @@
3030
* ownership rights.
3131
*******************************************************************************
3232
*/
33-
33+
3434
#include "sleep_api.h"
35-
#include "us_ticker_api.h"
3635
#include "cmsis.h"
3736
#include "pwrman_regs.h"
3837
#include "pwrseq_regs.h"
3938
#include "ioman_regs.h"
4039
#include "rtc_regs.h"
4140

42-
#define MIN_DEEP_SLEEP_US 500
43-
44-
uint64_t rtc_read_us(void);
45-
void rtc_set_wakeup(uint64_t wakeupUs);
46-
void us_ticker_deinit(void);
47-
void us_ticker_set(timestamp_t timestamp);
48-
4941
static mxc_uart_regs_t *stdio_uart = (mxc_uart_regs_t*)STDIO_UART;
5042

5143
// Normal wait mode
@@ -80,38 +72,11 @@ static void clearAllGPIOWUD(void)
8072
// Low-power stop mode
8173
void deepsleep(void)
8274
{
83-
uint64_t sleepStartRtcUs;
84-
uint32_t sleepStartTickerUs;
85-
int32_t sleepDurationUs;
86-
uint64_t sleepEndRtcUs;
87-
uint64_t elapsedUs;
88-
8975
__disable_irq();
9076

9177
// Wait for all STDIO characters to be sent. The UART clock will stop.
9278
while (stdio_uart->status & MXC_F_UART_STATUS_TX_BUSY);
9379

94-
// Record the current times
95-
sleepStartRtcUs = rtc_read_us();
96-
sleepStartTickerUs = us_ticker_read();
97-
98-
// Get the next mbed timer expiration
99-
timestamp_t next_event = 0;
100-
us_ticker_get_next_timestamp(&next_event);
101-
sleepDurationUs = next_event - sleepStartTickerUs;
102-
103-
if (sleepDurationUs < MIN_DEEP_SLEEP_US) {
104-
/* The next wakeup is too soon. */
105-
__enable_irq();
106-
return;
107-
}
108-
109-
// Disable the us_ticker. It won't be clocked in DeepSleep
110-
us_ticker_deinit();
111-
112-
// Prepare to wakeup from the RTC
113-
rtc_set_wakeup(sleepStartRtcUs + sleepDurationUs);
114-
11580
// Prepare for LP1
11681
uint32_t reg0 = MXC_PWRSEQ->reg0;
11782
reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_SVM3EN_SLP; // disable VDD3 SVM during sleep mode
@@ -151,19 +116,8 @@ void deepsleep(void)
151116
// Woke up from LP1
152117

153118
// The RTC timer does not update until the next tick
154-
uint64_t tempUs = rtc_read_us();
155-
do {
156-
sleepEndRtcUs = rtc_read_us();
157-
} while(sleepEndRtcUs == tempUs);
158-
159-
// Get the elapsed time from the RTC. Wakeup could have been from some other event.
160-
elapsedUs = sleepEndRtcUs - sleepStartRtcUs;
161-
162-
// Update the us_ticker. It was not clocked during DeepSleep
163-
us_ticker_init();
164-
us_ticker_set(sleepStartTickerUs + elapsedUs);
165-
us_ticker_get_next_timestamp(&next_event);
166-
us_ticker_set_interrupt(next_event);
119+
uint32_t temp = MXC_RTCTMR->timer;
120+
while (MXC_RTCTMR->timer == temp);
167121

168122
__enable_irq();
169123
}

libraries/mbed/targets/hal/TARGET_Maxim/TARGET_MAX32600/us_ticker.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* ownership rights.
3131
*******************************************************************************
3232
*/
33-
33+
3434
#include "mbed_error.h"
3535
#include "us_ticker_api.h"
3636
#include "PeripheralNames.h"
@@ -53,7 +53,7 @@ static inline void inc_current_cnt(uint32_t inc) {
5353

5454
// Overflow the ticker when the us ticker overflows
5555
current_cnt += inc;
56-
if(current_cnt > MAX_TICK_VAL) {
56+
if (current_cnt > MAX_TICK_VAL) {
5757
current_cnt -= (MAX_TICK_VAL + 1);
5858
}
5959
}
@@ -64,7 +64,7 @@ static inline int event_passed(uint64_t current, uint64_t event) {
6464
// Determine if the event has already happened.
6565
// If the event is behind the current ticker, within a window,
6666
// then the event has already happened.
67-
if(((current < tick_win) && ((event < current) ||
67+
if (((current < tick_win) && ((event < current) ||
6868
(event > (MAX_TICK_VAL - (tick_win - current))))) ||
6969
((event < current) && (event > (current - tick_win)))) {
7070
return 1;
@@ -169,7 +169,7 @@ uint32_t us_ticker_read(void)
169169
{
170170
uint64_t current_cnt1, current_cnt2;
171171
uint32_t term_cnt, tmr_cnt;
172-
int intfl1, intfl2;
172+
uint32_t intfl1, intfl2;
173173

174174
if (!us_ticker_inited)
175175
us_ticker_init();
@@ -184,6 +184,7 @@ uint32_t us_ticker_read(void)
184184
current_cnt2 = current_cnt;
185185
} while ((current_cnt1 != current_cnt2) || (intfl1 != intfl2));
186186

187+
// Account for an unserviced interrupt
187188
if (intfl1) {
188189
current_cnt1 += term_cnt;
189190
}
@@ -197,6 +198,7 @@ uint32_t us_ticker_read(void)
197198
void us_ticker_set_interrupt(timestamp_t timestamp)
198199
{
199200
// Note: interrupts are disabled before this function is called.
201+
200202
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
201203

202204
if (US_TIMER->intfl) {

libraries/mbed/targets/hal/TARGET_Maxim/TARGET_MAX32610/device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464

6565
#define DEVICE_ERROR_PATTERN 1
6666

67+
#define DEVICE_LOWPOWERTIMER 1
68+
6769
#define DEVICE_CAN 0
6870
#define DEVICE_ETHERNET 0
6971

0 commit comments

Comments
 (0)