Skip to content

Commit 8cad2b8

Browse files
committed
Merge pull request #2 from mbedmicro/master
Merge upstream changes back into my fork
2 parents cc0ec3e + 7bc3af6 commit 8cad2b8

File tree

12 files changed

+274
-217
lines changed

12 files changed

+274
-217
lines changed

libraries/mbed/targets/cmsis/TARGET_Maxim/TARGET_MAX32600/system_max32600.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void SystemInit(void)
115115
{
116116
set_pwr_regs();
117117

118-
// enable instruction cache
118+
// Enable instruction cache
119119
ICC_Enable();
120120

121121
low_level_init();
@@ -135,9 +135,16 @@ void SystemInit(void)
135135
MXC_F_PWRMAN_PWR_RST_CTRL_IO_ACTIVE |
136136
MXC_F_PWRMAN_PWR_RST_CTRL_PULLUPS_ENABLED);
137137

138+
// Clear the first boot flag. Use low_level_init() if special handling is required.
139+
MXC_PWRSEQ->reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT;
140+
141+
// Enable the regulator
138142
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_CHZYEN_RUN;
139143

140-
// set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep
144+
// Mask all wakeups
145+
MXC_PWRSEQ->msk_flags = 0xFFFFFFFF;
146+
147+
// Set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep
141148
MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_RTOS_MODE;
142149

143150
SystemCoreClockUpdate();

libraries/mbed/targets/cmsis/TARGET_Maxim/TARGET_MAX32610/system_max32610.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void SystemInit(void)
118118
// Turn off PADX
119119
MXC_IOMAN->padx_control = 0x00000441;
120120

121-
// enable instruction cache
121+
// Enable instruction cache
122122
ICC_Enable();
123123

124124
low_level_init();
@@ -138,9 +138,16 @@ void SystemInit(void)
138138
MXC_F_PWRMAN_PWR_RST_CTRL_IO_ACTIVE |
139139
MXC_F_PWRMAN_PWR_RST_CTRL_PULLUPS_ENABLED);
140140

141+
// Clear the first boot flag. Use low_level_init() if special handling is required.
142+
MXC_PWRSEQ->reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT;
143+
144+
// Enable the regulator
141145
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_CHZYEN_RUN;
142146

143-
// set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep
147+
// Mask all wakeups
148+
MXC_PWRSEQ->msk_flags = 0xFFFFFFFF;
149+
150+
// Set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep
144151
MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_RTOS_MODE;
145152

146153
SystemCoreClockUpdate();

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

+2
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

+112-53
Original file line numberDiff line numberDiff line change
@@ -32,62 +32,77 @@
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+
44+
#define WINDOW 1000
45+
4046
static int rtc_inited = 0;
4147
static volatile uint32_t overflow_cnt = 0;
42-
static uint32_t overflow_alarm = 0;
48+
49+
static uint64_t rtc_read64(void);
4350

4451
//******************************************************************************
4552
static void overflow_handler(void)
4653
{
47-
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
54+
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_OVERFLOW;
55+
MXC_PWRSEQ->flags = MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER;
4856
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;
6157
}
6258

6359
//******************************************************************************
6460
void rtc_init(void)
6561
{
66-
if(rtc_inited) {
62+
if (rtc_inited) {
6763
return;
6864
}
6965
rtc_inited = 1;
7066

67+
overflow_cnt = 0;
68+
7169
// Enable the clock to the synchronizer
7270
MXC_CLKMAN->clk_ctrl_13_rtc_int_sync = MXC_E_CLKMAN_CLK_SCALE_ENABLED;
7371

7472
// Enable the clock to the RTC
7573
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN;
7674

77-
// Set the divider from the 4kHz clock
78-
MXC_RTCTMR->prescale = MXC_E_RTC_PRESCALE_DIV_2_0;
79-
80-
// Enable the overflow interrupt
81-
MXC_RTCTMR->inten |= MXC_F_RTC_FLAGS_OVERFLOW;
82-
8375
// Prepare interrupt handlers
84-
NVIC_SetVector(RTC0_IRQn, (uint32_t)alarm_handler);
76+
NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
8577
NVIC_EnableIRQ(RTC0_IRQn);
8678
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
8779
NVIC_EnableIRQ(RTC3_IRQn);
8880

89-
// Enable the RTC
90-
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE;
81+
// Enable wakeup on RTC rollover
82+
MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER;
83+
84+
/* RTC registers are only reset on a power cycle. Do not reconfigure the RTC
85+
* if it is already running.
86+
*/
87+
if (!(MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_ENABLE)) {
88+
// Set the clock divider
89+
MXC_RTCTMR->prescale = PRESCALE_VAL;
90+
91+
// Enable the overflow interrupt
92+
MXC_RTCTMR->inten |= MXC_F_RTC_FLAGS_OVERFLOW;
93+
94+
// Restart the timer from 0
95+
MXC_RTCTMR->timer = 0;
96+
97+
// Enable the RTC
98+
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE;
99+
}
100+
}
101+
102+
//******************************************************************************
103+
void lp_ticker_init(void)
104+
{
105+
rtc_init();
91106
}
92107

93108
//******************************************************************************
@@ -118,73 +133,117 @@ int rtc_isenabled(void)
118133
//******************************************************************************
119134
time_t rtc_read(void)
120135
{
121-
unsigned int shift_amt;
122136
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;
137+
uint32_t ovf1, ovf2;
126138

127139
// Ensure coherency between overflow_cnt and timer
128140
do {
129141
ovf_cnt_1 = overflow_cnt;
142+
ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
130143
timer_cnt = MXC_RTCTMR->timer;
144+
ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
131145
ovf_cnt_2 = overflow_cnt;
132-
} while (ovf_cnt_1 != ovf_cnt_2);
146+
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
133147

134-
return (timer_cnt >> shift_amt) + (ovf_cnt_1 << (32 - shift_amt));
148+
// Account for an unserviced interrupt
149+
if (ovf1) {
150+
ovf_cnt_1++;
151+
}
152+
153+
return (timer_cnt >> SHIFT_AMT) + (ovf_cnt_1 << (32 - SHIFT_AMT));
135154
}
136155

137156
//******************************************************************************
138-
uint64_t rtc_read_us(void)
157+
static uint64_t rtc_read64(void)
139158
{
140-
unsigned int shift_amt;
141159
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;
160+
uint32_t ovf1, ovf2;
161+
uint64_t current_us;
146162

147163
// Ensure coherency between overflow_cnt and timer
148164
do {
149165
ovf_cnt_1 = overflow_cnt;
166+
ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
150167
timer_cnt = MXC_RTCTMR->timer;
168+
ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
151169
ovf_cnt_2 = overflow_cnt;
152-
} while (ovf_cnt_1 != ovf_cnt_2);
170+
} while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
171+
172+
// Account for an unserviced interrupt
173+
if (ovf1) {
174+
ovf_cnt_1++;
175+
}
153176

154-
currentUs = (((uint64_t)timer_cnt * 1000000) >> shift_amt) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - shift_amt));
177+
current_us = (((uint64_t)timer_cnt * 1000000) >> SHIFT_AMT) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - SHIFT_AMT));
155178

156-
return currentUs;
179+
return current_us;
157180
}
158181

159182
//******************************************************************************
160183
void rtc_write(time_t t)
161184
{
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-
165185
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);
186+
MXC_RTCTMR->timer = t << SHIFT_AMT;
187+
overflow_cnt = t >> (32 - SHIFT_AMT);
168188
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; // enable the timer while updating
169189
}
170190

171191
//******************************************************************************
172-
void rtc_set_wakeup(uint64_t wakeupUs)
192+
void lp_ticker_set_interrupt(timestamp_t timestamp)
173193
{
174-
// Account for a change in the default prescaler
175-
unsigned int shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
194+
uint32_t comp_value;
195+
uint64_t curr_ts64;
196+
uint64_t ts64;
197+
198+
// Note: interrupts are disabled before this function is called.
176199

177200
// Disable the alarm while it is prepared
178201
MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
179-
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; // clear interrupt
180202

181-
overflow_alarm = (wakeupUs >> (32 - shift_amt)) / 1000000;
203+
curr_ts64 = rtc_read64();
204+
ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL);
182205

183-
if (overflow_alarm == overflow_cnt) {
184-
MXC_RTCTMR->comp[0] = (wakeupUs << shift_amt) / 1000000;
185-
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
206+
// If this event is older than a recent window, it must be in the future
207+
if ((ts64 < (curr_ts64 - WINDOW)) && ((curr_ts64 - WINDOW) < curr_ts64)) {
208+
ts64 += 0x100000000ULL;
186209
}
187210

211+
uint32_t timer = MXC_RTCTMR->timer;
212+
if (ts64 <= curr_ts64) {
213+
// This event has already occurred. Set the alarm to expire immediately.
214+
comp_value = timer + 1;
215+
} else {
216+
comp_value = (ts64 << SHIFT_AMT) / 1000000;
217+
}
218+
219+
// Ensure that the compare value is far enough in the future to guarantee the interrupt occurs.
220+
if ((comp_value < (timer + 2)) && (comp_value > (timer - 10))) {
221+
comp_value = timer + 2;
222+
}
223+
224+
MXC_RTCTMR->comp[0] = comp_value;
225+
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; // clear interrupt
226+
MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; // enable the interrupt
227+
188228
// Enable wakeup from RTC
189-
MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER | MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0);
229+
MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0;
230+
}
231+
232+
//******************************************************************************
233+
inline void lp_ticker_disable_interrupt(void)
234+
{
235+
MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
236+
}
237+
238+
//******************************************************************************
239+
inline void lp_ticker_clear_interrupt(void)
240+
{
241+
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
242+
MXC_PWRSEQ->flags = MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0;
243+
}
244+
245+
//******************************************************************************
246+
inline uint32_t lp_ticker_read(void)
247+
{
248+
return rtc_read64();
190249
}

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

+3-49
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
}

0 commit comments

Comments
 (0)