Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_blinky-bmd-200 bmd-200_accel_demo firstRig
Fork of mbed-src by
Revision 540:c48d7048ab6e, committed 2015-05-07
- Comitter:
- mbed_official
- Date:
- Thu May 07 09:00:08 2015 +0100
- Parent:
- 539:35ad5cbb2f6a
- Child:
- 541:c61a9ac6f5c2
- Commit message:
- Synchronized with git revision a1e04f782bf013aeb4122c3ec408e3b011de60ed
Full URL: https://github.com/mbedmicro/mbed/commit/a1e04f782bf013aeb4122c3ec408e3b011de60ed/
MAX32600MBED,MAXWSNENV - Add low-power ticker.
Changed in this revision
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32600/device.h Wed May 06 14:15:12 2015 +0100 +++ b/targets/hal/TARGET_Maxim/TARGET_MAX32600/device.h Thu May 07 09:00:08 2015 +0100 @@ -64,6 +64,8 @@ #define DEVICE_ERROR_PATTERN 1 +#define DEVICE_LOWPOWERTIMER 1 + #define DEVICE_CAN 0 #define DEVICE_ETHERNET 0
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32600/rtc_api.c Wed May 06 14:15:12 2015 +0100
+++ b/targets/hal/TARGET_Maxim/TARGET_MAX32600/rtc_api.c Thu May 07 09:00:08 2015 +0100
@@ -32,56 +32,51 @@
*/
#include "rtc_api.h"
+#include "lp_ticker_api.h"
#include "cmsis.h"
#include "rtc_regs.h"
#include "pwrseq_regs.h"
#include "clkman_regs.h"
+#define PRESCALE_VAL MXC_E_RTC_PRESCALE_DIV_2_0 // Set the divider for the 4kHz clock
+#define SHIFT_AMT (MXC_E_RTC_PRESCALE_DIV_2_12 - PRESCALE_VAL)
+
static int rtc_inited = 0;
static volatile uint32_t overflow_cnt = 0;
-static uint32_t overflow_alarm = 0;
+
+static uint64_t rtc_read64(void);
//******************************************************************************
static void overflow_handler(void)
{
- MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
+ MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_OVERFLOW;
overflow_cnt++;
-
- if (overflow_cnt == overflow_alarm) {
- // Enable the comparator interrupt for the alarm
- MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
- }
-}
-
-//******************************************************************************
-static void alarm_handler(void)
-{
- MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
- MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
}
//******************************************************************************
void rtc_init(void)
{
- if(rtc_inited) {
+ if (rtc_inited) {
return;
}
rtc_inited = 1;
+ overflow_cnt = 0;
+
// Enable the clock to the synchronizer
MXC_CLKMAN->clk_ctrl_13_rtc_int_sync = MXC_E_CLKMAN_CLK_SCALE_ENABLED;
// Enable the clock to the RTC
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN;
- // Set the divider from the 4kHz clock
- MXC_RTCTMR->prescale = MXC_E_RTC_PRESCALE_DIV_2_0;
+ // Set the clock divider
+ MXC_RTCTMR->prescale = PRESCALE_VAL;
// Enable the overflow interrupt
MXC_RTCTMR->inten |= MXC_F_RTC_FLAGS_OVERFLOW;
// Prepare interrupt handlers
- NVIC_SetVector(RTC0_IRQn, (uint32_t)alarm_handler);
+ NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
NVIC_EnableIRQ(RTC0_IRQn);
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
NVIC_EnableIRQ(RTC3_IRQn);
@@ -91,6 +86,12 @@
}
//******************************************************************************
+void lp_ticker_init(void)
+{
+ rtc_init();
+}
+
+//******************************************************************************
void rtc_free(void)
{
if (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_ENABLE) {
@@ -118,73 +119,104 @@
//******************************************************************************
time_t rtc_read(void)
{
- unsigned int shift_amt;
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
-
- // Account for a change in the default prescaler
- shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
+ uint32_t ovf1, ovf2;
// Ensure coherency between overflow_cnt and timer
do {
ovf_cnt_1 = overflow_cnt;
+ ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
timer_cnt = MXC_RTCTMR->timer;
+ ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
ovf_cnt_2 = overflow_cnt;
- } while (ovf_cnt_1 != ovf_cnt_2);
+ } while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
- return (timer_cnt >> shift_amt) + (ovf_cnt_1 << (32 - shift_amt));
+ // Account for an unserviced interrupt
+ if (ovf1) {
+ ovf_cnt_1++;
+ }
+
+ return (timer_cnt >> SHIFT_AMT) + (ovf_cnt_1 << (32 - SHIFT_AMT));
}
//******************************************************************************
-uint64_t rtc_read_us(void)
+static uint64_t rtc_read64(void)
{
- unsigned int shift_amt;
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
- uint64_t currentUs;
-
- // Account for a change in the default prescaler
- shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
+ uint32_t ovf1, ovf2;
+ uint64_t current_us;
// Ensure coherency between overflow_cnt and timer
do {
ovf_cnt_1 = overflow_cnt;
+ ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
timer_cnt = MXC_RTCTMR->timer;
+ ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
ovf_cnt_2 = overflow_cnt;
- } while (ovf_cnt_1 != ovf_cnt_2);
+ } while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
- currentUs = (((uint64_t)timer_cnt * 1000000) >> shift_amt) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - shift_amt));
+ // Account for an unserviced interrupt
+ if (ovf1) {
+ ovf_cnt_1++;
+ }
- return currentUs;
+ current_us = (((uint64_t)timer_cnt * 1000000) >> SHIFT_AMT) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - SHIFT_AMT));
+
+ return current_us;
}
//******************************************************************************
void rtc_write(time_t t)
{
- // Account for a change in the default prescaler
- unsigned int shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
-
MXC_RTCTMR->ctrl &= ~MXC_F_RTC_CTRL_ENABLE; // disable the timer while updating
- MXC_RTCTMR->timer = t << shift_amt;
- overflow_cnt = t >> (32 - shift_amt);
+ MXC_RTCTMR->timer = t << SHIFT_AMT;
+ overflow_cnt = t >> (32 - SHIFT_AMT);
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; // enable the timer while updating
}
//******************************************************************************
-void rtc_set_wakeup(uint64_t wakeupUs)
+void lp_ticker_set_interrupt(timestamp_t timestamp)
{
- // Account for a change in the default prescaler
- unsigned int shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
+ // Note: interrupts are disabled before this function is called.
// Disable the alarm while it is prepared
MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; // clear interrupt
- overflow_alarm = (wakeupUs >> (32 - shift_amt)) / 1000000;
+ uint64_t curr_ts64 = rtc_read64();
+ uint64_t ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL);
+ if (ts64 < curr_ts64) {
+ if (ts64 < (curr_ts64 - 1000)) {
+ ts64 += 0x100000000ULL;
+ } else {
+ // This event has already occurred. Set the alarm to expire immediately.
+ MXC_RTCTMR->comp[0] = MXC_RTCTMR->timer + 2;
+ MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
+ return;
+ }
+ }
- if (overflow_alarm == overflow_cnt) {
- MXC_RTCTMR->comp[0] = (wakeupUs << shift_amt) / 1000000;
- MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
- }
+ MXC_RTCTMR->comp[0] = (ts64 << SHIFT_AMT) / 1000000;
+ MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
// Enable wakeup from RTC
MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER | MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0);
}
+
+//******************************************************************************
+inline void lp_ticker_disable_interrupt(void)
+{
+ MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
+}
+
+//******************************************************************************
+inline void lp_ticker_clear_interrupt(void)
+{
+ MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
+}
+
+//******************************************************************************
+inline uint32_t lp_ticker_read(void)
+{
+ return rtc_read64();
+}
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32600/sleep.c Wed May 06 14:15:12 2015 +0100
+++ b/targets/hal/TARGET_Maxim/TARGET_MAX32600/sleep.c Thu May 07 09:00:08 2015 +0100
@@ -30,22 +30,14 @@
* ownership rights.
*******************************************************************************
*/
-
+
#include "sleep_api.h"
-#include "us_ticker_api.h"
#include "cmsis.h"
#include "pwrman_regs.h"
#include "pwrseq_regs.h"
#include "ioman_regs.h"
#include "rtc_regs.h"
-#define MIN_DEEP_SLEEP_US 500
-
-uint64_t rtc_read_us(void);
-void rtc_set_wakeup(uint64_t wakeupUs);
-void us_ticker_deinit(void);
-void us_ticker_set(timestamp_t timestamp);
-
static mxc_uart_regs_t *stdio_uart = (mxc_uart_regs_t*)STDIO_UART;
// Normal wait mode
@@ -80,38 +72,11 @@
// Low-power stop mode
void deepsleep(void)
{
- uint64_t sleepStartRtcUs;
- uint32_t sleepStartTickerUs;
- int32_t sleepDurationUs;
- uint64_t sleepEndRtcUs;
- uint64_t elapsedUs;
-
__disable_irq();
// Wait for all STDIO characters to be sent. The UART clock will stop.
while (stdio_uart->status & MXC_F_UART_STATUS_TX_BUSY);
- // Record the current times
- sleepStartRtcUs = rtc_read_us();
- sleepStartTickerUs = us_ticker_read();
-
- // Get the next mbed timer expiration
- timestamp_t next_event = 0;
- us_ticker_get_next_timestamp(&next_event);
- sleepDurationUs = next_event - sleepStartTickerUs;
-
- if (sleepDurationUs < MIN_DEEP_SLEEP_US) {
- /* The next wakeup is too soon. */
- __enable_irq();
- return;
- }
-
- // Disable the us_ticker. It won't be clocked in DeepSleep
- us_ticker_deinit();
-
- // Prepare to wakeup from the RTC
- rtc_set_wakeup(sleepStartRtcUs + sleepDurationUs);
-
// Prepare for LP1
uint32_t reg0 = MXC_PWRSEQ->reg0;
reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_SVM3EN_SLP; // disable VDD3 SVM during sleep mode
@@ -151,19 +116,8 @@
// Woke up from LP1
// The RTC timer does not update until the next tick
- uint64_t tempUs = rtc_read_us();
- do {
- sleepEndRtcUs = rtc_read_us();
- } while(sleepEndRtcUs == tempUs);
-
- // Get the elapsed time from the RTC. Wakeup could have been from some other event.
- elapsedUs = sleepEndRtcUs - sleepStartRtcUs;
-
- // Update the us_ticker. It was not clocked during DeepSleep
- us_ticker_init();
- us_ticker_set(sleepStartTickerUs + elapsedUs);
- us_ticker_get_next_timestamp(&next_event);
- us_ticker_set_interrupt(next_event);
+ uint32_t temp = MXC_RTCTMR->timer;
+ while (MXC_RTCTMR->timer == temp);
__enable_irq();
}
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32600/us_ticker.c Wed May 06 14:15:12 2015 +0100
+++ b/targets/hal/TARGET_Maxim/TARGET_MAX32600/us_ticker.c Thu May 07 09:00:08 2015 +0100
@@ -30,7 +30,7 @@
* ownership rights.
*******************************************************************************
*/
-
+
#include "mbed_error.h"
#include "us_ticker_api.h"
#include "PeripheralNames.h"
@@ -53,7 +53,7 @@
// Overflow the ticker when the us ticker overflows
current_cnt += inc;
- if(current_cnt > MAX_TICK_VAL) {
+ if (current_cnt > MAX_TICK_VAL) {
current_cnt -= (MAX_TICK_VAL + 1);
}
}
@@ -64,7 +64,7 @@
// Determine if the event has already happened.
// If the event is behind the current ticker, within a window,
// then the event has already happened.
- if(((current < tick_win) && ((event < current) ||
+ if (((current < tick_win) && ((event < current) ||
(event > (MAX_TICK_VAL - (tick_win - current))))) ||
((event < current) && (event > (current - tick_win)))) {
return 1;
@@ -169,7 +169,7 @@
{
uint64_t current_cnt1, current_cnt2;
uint32_t term_cnt, tmr_cnt;
- int intfl1, intfl2;
+ uint32_t intfl1, intfl2;
if (!us_ticker_inited)
us_ticker_init();
@@ -184,6 +184,7 @@
current_cnt2 = current_cnt;
} while ((current_cnt1 != current_cnt2) || (intfl1 != intfl2));
+ // Account for an unserviced interrupt
if (intfl1) {
current_cnt1 += term_cnt;
}
@@ -197,6 +198,7 @@
void us_ticker_set_interrupt(timestamp_t timestamp)
{
// Note: interrupts are disabled before this function is called.
+
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
if (US_TIMER->intfl) {
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32610/device.h Wed May 06 14:15:12 2015 +0100 +++ b/targets/hal/TARGET_Maxim/TARGET_MAX32610/device.h Thu May 07 09:00:08 2015 +0100 @@ -64,6 +64,8 @@ #define DEVICE_ERROR_PATTERN 1 +#define DEVICE_LOWPOWERTIMER 1 + #define DEVICE_CAN 0 #define DEVICE_ETHERNET 0
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32610/rtc_api.c Wed May 06 14:15:12 2015 +0100
+++ b/targets/hal/TARGET_Maxim/TARGET_MAX32610/rtc_api.c Thu May 07 09:00:08 2015 +0100
@@ -32,56 +32,51 @@
*/
#include "rtc_api.h"
+#include "lp_ticker_api.h"
#include "cmsis.h"
#include "rtc_regs.h"
#include "pwrseq_regs.h"
#include "clkman_regs.h"
+#define PRESCALE_VAL MXC_E_RTC_PRESCALE_DIV_2_0 // Set the divider for the 4kHz clock
+#define SHIFT_AMT (MXC_E_RTC_PRESCALE_DIV_2_12 - PRESCALE_VAL)
+
static int rtc_inited = 0;
static volatile uint32_t overflow_cnt = 0;
-static uint32_t overflow_alarm = 0;
+
+static uint64_t rtc_read64(void);
//******************************************************************************
static void overflow_handler(void)
{
- MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
+ MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_OVERFLOW;
overflow_cnt++;
-
- if (overflow_cnt == overflow_alarm) {
- // Enable the comparator interrupt for the alarm
- MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
- }
-}
-
-//******************************************************************************
-static void alarm_handler(void)
-{
- MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
- MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
}
//******************************************************************************
void rtc_init(void)
{
- if(rtc_inited) {
+ if (rtc_inited) {
return;
}
rtc_inited = 1;
+ overflow_cnt = 0;
+
// Enable the clock to the synchronizer
MXC_CLKMAN->clk_ctrl_13_rtc_int_sync = MXC_E_CLKMAN_CLK_SCALE_ENABLED;
// Enable the clock to the RTC
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN;
- // Set the divider from the 4kHz clock
- MXC_RTCTMR->prescale = MXC_E_RTC_PRESCALE_DIV_2_0;
+ // Set the clock divider
+ MXC_RTCTMR->prescale = PRESCALE_VAL;
// Enable the overflow interrupt
MXC_RTCTMR->inten |= MXC_F_RTC_FLAGS_OVERFLOW;
// Prepare interrupt handlers
- NVIC_SetVector(RTC0_IRQn, (uint32_t)alarm_handler);
+ NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler);
NVIC_EnableIRQ(RTC0_IRQn);
NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler);
NVIC_EnableIRQ(RTC3_IRQn);
@@ -91,6 +86,12 @@
}
//******************************************************************************
+void lp_ticker_init(void)
+{
+ rtc_init();
+}
+
+//******************************************************************************
void rtc_free(void)
{
if (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_ENABLE) {
@@ -118,73 +119,104 @@
//******************************************************************************
time_t rtc_read(void)
{
- unsigned int shift_amt;
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
-
- // Account for a change in the default prescaler
- shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
+ uint32_t ovf1, ovf2;
// Ensure coherency between overflow_cnt and timer
do {
ovf_cnt_1 = overflow_cnt;
+ ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
timer_cnt = MXC_RTCTMR->timer;
+ ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
ovf_cnt_2 = overflow_cnt;
- } while (ovf_cnt_1 != ovf_cnt_2);
+ } while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
- return (timer_cnt >> shift_amt) + (ovf_cnt_1 << (32 - shift_amt));
+ // Account for an unserviced interrupt
+ if (ovf1) {
+ ovf_cnt_1++;
+ }
+
+ return (timer_cnt >> SHIFT_AMT) + (ovf_cnt_1 << (32 - SHIFT_AMT));
}
//******************************************************************************
-uint64_t rtc_read_us(void)
+static uint64_t rtc_read64(void)
{
- unsigned int shift_amt;
uint32_t ovf_cnt_1, ovf_cnt_2, timer_cnt;
- uint64_t currentUs;
-
- // Account for a change in the default prescaler
- shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
+ uint32_t ovf1, ovf2;
+ uint64_t current_us;
// Ensure coherency between overflow_cnt and timer
do {
ovf_cnt_1 = overflow_cnt;
+ ovf1 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
timer_cnt = MXC_RTCTMR->timer;
+ ovf2 = MXC_RTCTMR->flags & MXC_F_RTC_FLAGS_OVERFLOW;
ovf_cnt_2 = overflow_cnt;
- } while (ovf_cnt_1 != ovf_cnt_2);
+ } while ((ovf_cnt_1 != ovf_cnt_2) || (ovf1 != ovf2));
- currentUs = (((uint64_t)timer_cnt * 1000000) >> shift_amt) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - shift_amt));
+ // Account for an unserviced interrupt
+ if (ovf1) {
+ ovf_cnt_1++;
+ }
- return currentUs;
+ current_us = (((uint64_t)timer_cnt * 1000000) >> SHIFT_AMT) + (((uint64_t)ovf_cnt_1 * 1000000) << (32 - SHIFT_AMT));
+
+ return current_us;
}
//******************************************************************************
void rtc_write(time_t t)
{
- // Account for a change in the default prescaler
- unsigned int shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
-
MXC_RTCTMR->ctrl &= ~MXC_F_RTC_CTRL_ENABLE; // disable the timer while updating
- MXC_RTCTMR->timer = t << shift_amt;
- overflow_cnt = t >> (32 - shift_amt);
+ MXC_RTCTMR->timer = t << SHIFT_AMT;
+ overflow_cnt = t >> (32 - SHIFT_AMT);
MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; // enable the timer while updating
}
//******************************************************************************
-void rtc_set_wakeup(uint64_t wakeupUs)
+void lp_ticker_set_interrupt(timestamp_t timestamp)
{
- // Account for a change in the default prescaler
- unsigned int shift_amt = MXC_E_RTC_PRESCALE_DIV_2_12 - MXC_RTCTMR->prescale;
+ // Note: interrupts are disabled before this function is called.
// Disable the alarm while it is prepared
MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; // clear interrupt
- overflow_alarm = (wakeupUs >> (32 - shift_amt)) / 1000000;
+ uint64_t curr_ts64 = rtc_read64();
+ uint64_t ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL);
+ if (ts64 < curr_ts64) {
+ if (ts64 < (curr_ts64 - 1000)) {
+ ts64 += 0x100000000ULL;
+ } else {
+ // This event has already occurred. Set the alarm to expire immediately.
+ MXC_RTCTMR->comp[0] = MXC_RTCTMR->timer + 2;
+ MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
+ return;
+ }
+ }
- if (overflow_alarm == overflow_cnt) {
- MXC_RTCTMR->comp[0] = (wakeupUs << shift_amt) / 1000000;
- MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
- }
+ MXC_RTCTMR->comp[0] = (ts64 << SHIFT_AMT) / 1000000;
+ MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0;
// Enable wakeup from RTC
MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER | MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0);
}
+
+//******************************************************************************
+inline void lp_ticker_disable_interrupt(void)
+{
+ MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0;
+}
+
+//******************************************************************************
+inline void lp_ticker_clear_interrupt(void)
+{
+ MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS;
+}
+
+//******************************************************************************
+inline uint32_t lp_ticker_read(void)
+{
+ return rtc_read64();
+}
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32610/sleep.c Wed May 06 14:15:12 2015 +0100
+++ b/targets/hal/TARGET_Maxim/TARGET_MAX32610/sleep.c Thu May 07 09:00:08 2015 +0100
@@ -30,22 +30,14 @@
* ownership rights.
*******************************************************************************
*/
-
+
#include "sleep_api.h"
-#include "us_ticker_api.h"
#include "cmsis.h"
#include "pwrman_regs.h"
#include "pwrseq_regs.h"
#include "ioman_regs.h"
#include "rtc_regs.h"
-#define MIN_DEEP_SLEEP_US 500
-
-uint64_t rtc_read_us(void);
-void rtc_set_wakeup(uint64_t wakeupUs);
-void us_ticker_deinit(void);
-void us_ticker_set(timestamp_t timestamp);
-
static mxc_uart_regs_t *stdio_uart = (mxc_uart_regs_t*)STDIO_UART;
// Normal wait mode
@@ -80,38 +72,11 @@
// Low-power stop mode
void deepsleep(void)
{
- uint64_t sleepStartRtcUs;
- uint32_t sleepStartTickerUs;
- int32_t sleepDurationUs;
- uint64_t sleepEndRtcUs;
- uint64_t elapsedUs;
-
__disable_irq();
// Wait for all STDIO characters to be sent. The UART clock will stop.
while (stdio_uart->status & MXC_F_UART_STATUS_TX_BUSY);
- // Record the current times
- sleepStartRtcUs = rtc_read_us();
- sleepStartTickerUs = us_ticker_read();
-
- // Get the next mbed timer expiration
- timestamp_t next_event = 0;
- us_ticker_get_next_timestamp(&next_event);
- sleepDurationUs = next_event - sleepStartTickerUs;
-
- if (sleepDurationUs < MIN_DEEP_SLEEP_US) {
- /* The next wakeup is too soon. */
- __enable_irq();
- return;
- }
-
- // Disable the us_ticker. It won't be clocked in DeepSleep
- us_ticker_deinit();
-
- // Prepare to wakeup from the RTC
- rtc_set_wakeup(sleepStartRtcUs + sleepDurationUs);
-
// Prepare for LP1
uint32_t reg0 = MXC_PWRSEQ->reg0;
reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_SVM3EN_SLP; // disable VDD3 SVM during sleep mode
@@ -151,19 +116,8 @@
// Woke up from LP1
// The RTC timer does not update until the next tick
- uint64_t tempUs = rtc_read_us();
- do {
- sleepEndRtcUs = rtc_read_us();
- } while(sleepEndRtcUs == tempUs);
-
- // Get the elapsed time from the RTC. Wakeup could have been from some other event.
- elapsedUs = sleepEndRtcUs - sleepStartRtcUs;
-
- // Update the us_ticker. It was not clocked during DeepSleep
- us_ticker_init();
- us_ticker_set(sleepStartTickerUs + elapsedUs);
- us_ticker_get_next_timestamp(&next_event);
- us_ticker_set_interrupt(next_event);
+ uint32_t temp = MXC_RTCTMR->timer;
+ while (MXC_RTCTMR->timer == temp);
__enable_irq();
}
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32610/us_ticker.c Wed May 06 14:15:12 2015 +0100
+++ b/targets/hal/TARGET_Maxim/TARGET_MAX32610/us_ticker.c Thu May 07 09:00:08 2015 +0100
@@ -30,7 +30,7 @@
* ownership rights.
*******************************************************************************
*/
-
+
#include "mbed_error.h"
#include "us_ticker_api.h"
#include "PeripheralNames.h"
@@ -53,7 +53,7 @@
// Overflow the ticker when the us ticker overflows
current_cnt += inc;
- if(current_cnt > MAX_TICK_VAL) {
+ if (current_cnt > MAX_TICK_VAL) {
current_cnt -= (MAX_TICK_VAL + 1);
}
}
@@ -64,7 +64,7 @@
// Determine if the event has already happened.
// If the event is behind the current ticker, within a window,
// then the event has already happened.
- if(((current < tick_win) && ((event < current) ||
+ if (((current < tick_win) && ((event < current) ||
(event > (MAX_TICK_VAL - (tick_win - current))))) ||
((event < current) && (event > (current - tick_win)))) {
return 1;
@@ -169,7 +169,7 @@
{
uint64_t current_cnt1, current_cnt2;
uint32_t term_cnt, tmr_cnt;
- int intfl1, intfl2;
+ uint32_t intfl1, intfl2;
if (!us_ticker_inited)
us_ticker_init();
@@ -184,6 +184,7 @@
current_cnt2 = current_cnt;
} while ((current_cnt1 != current_cnt2) || (intfl1 != intfl2));
+ // Account for an unserviced interrupt
if (intfl1) {
current_cnt1 += term_cnt;
}
@@ -197,6 +198,7 @@
void us_ticker_set_interrupt(timestamp_t timestamp)
{
// Note: interrupts are disabled before this function is called.
+
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
if (US_TIMER->intfl) {
