mbed library sources(for async_print)
Fork of mbed-src by
Revision 538:3c6246291cdb, committed 2015-05-11
- Comitter:
- mbed_official
- Date:
- Mon May 11 08:15:07 2015 +0100
- Parent:
- 537:c61a9ac6f5c2
- Child:
- 539:aad7ca793a89
- Commit message:
- Synchronized with git revision 77b4a7bc786dd2baf633cc7140deb6b0d6ec4463
Full URL: https://github.com/mbedmicro/mbed/commit/77b4a7bc786dd2baf633cc7140deb6b0d6ec4463/
MAX32600MBED,MAXWSNENV - addressed low-power ticker corner cases
Changed in this revision
--- a/targets/cmsis/TARGET_Maxim/TARGET_MAX32600/system_max32600.c Thu May 07 09:15:08 2015 +0100 +++ b/targets/cmsis/TARGET_Maxim/TARGET_MAX32600/system_max32600.c Mon May 11 08:15:07 2015 +0100 @@ -115,7 +115,7 @@ { set_pwr_regs(); - // enable instruction cache + // Enable instruction cache ICC_Enable(); low_level_init(); @@ -135,9 +135,16 @@ MXC_F_PWRMAN_PWR_RST_CTRL_IO_ACTIVE | MXC_F_PWRMAN_PWR_RST_CTRL_PULLUPS_ENABLED); + // Clear the first boot flag. Use low_level_init() if special handling is required. + MXC_PWRSEQ->reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT; + + // Enable the regulator MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_CHZYEN_RUN; - // set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep + // Mask all wakeups + MXC_PWRSEQ->msk_flags = 0xFFFFFFFF; + + // Set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_RTOS_MODE; SystemCoreClockUpdate();
--- a/targets/cmsis/TARGET_Maxim/TARGET_MAX32610/system_max32610.c Thu May 07 09:15:08 2015 +0100 +++ b/targets/cmsis/TARGET_Maxim/TARGET_MAX32610/system_max32610.c Mon May 11 08:15:07 2015 +0100 @@ -118,7 +118,7 @@ // Turn off PADX MXC_IOMAN->padx_control = 0x00000441; - // enable instruction cache + // Enable instruction cache ICC_Enable(); low_level_init(); @@ -138,9 +138,16 @@ MXC_F_PWRMAN_PWR_RST_CTRL_IO_ACTIVE | MXC_F_PWRMAN_PWR_RST_CTRL_PULLUPS_ENABLED); + // Clear the first boot flag. Use low_level_init() if special handling is required. + MXC_PWRSEQ->reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT; + + // Enable the regulator MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_CHZYEN_RUN; - // set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep + // Mask all wakeups + MXC_PWRSEQ->msk_flags = 0xFFFFFFFF; + + // Set systick to the RTC input 32.768kHz clock, not system clock; this is needed to keep JTAG alive during sleep MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_RTOS_MODE; SystemCoreClockUpdate();
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32600/rtc_api.c Thu May 07 09:15:08 2015 +0100 +++ b/targets/hal/TARGET_Maxim/TARGET_MAX32600/rtc_api.c Mon May 11 08:15:07 2015 +0100 @@ -41,6 +41,8 @@ #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) +#define WINDOW 1000 + static int rtc_inited = 0; static volatile uint32_t overflow_cnt = 0; @@ -50,6 +52,7 @@ static void overflow_handler(void) { MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_OVERFLOW; + MXC_PWRSEQ->flags = MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER; overflow_cnt++; } @@ -69,20 +72,31 @@ // Enable the clock to the RTC MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN; - // 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)lp_ticker_irq_handler); NVIC_EnableIRQ(RTC0_IRQn); NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler); NVIC_EnableIRQ(RTC3_IRQn); - // Enable the RTC - MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; + // Enable wakeup on RTC rollover + MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER; + + /* RTC registers are only reset on a power cycle. Do not reconfigure the RTC + * if it is already running. + */ + if (!(MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_ENABLE)) { + // Set the clock divider + MXC_RTCTMR->prescale = PRESCALE_VAL; + + // Enable the overflow interrupt + MXC_RTCTMR->inten |= MXC_F_RTC_FLAGS_OVERFLOW; + + // Restart the timer from 0 + MXC_RTCTMR->timer = 0; + + // Enable the RTC + MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; + } } //****************************************************************************** @@ -177,30 +191,42 @@ //****************************************************************************** void lp_ticker_set_interrupt(timestamp_t timestamp) { + uint32_t comp_value; + uint64_t curr_ts64; + uint64_t ts64; + // 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 + + curr_ts64 = rtc_read64(); + ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL); - 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 this event is older than a recent window, it must be in the future + if ((ts64 < (curr_ts64 - WINDOW)) && ((curr_ts64 - WINDOW) < curr_ts64)) { + ts64 += 0x100000000ULL; } - MXC_RTCTMR->comp[0] = (ts64 << SHIFT_AMT) / 1000000; - MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; + uint32_t timer = MXC_RTCTMR->timer; + if (ts64 <= curr_ts64) { + // This event has already occurred. Set the alarm to expire immediately. + comp_value = timer + 1; + } else { + comp_value = (ts64 << SHIFT_AMT) / 1000000; + } + + // Ensure that the compare value is far enough in the future to guarantee the interrupt occurs. + if ((comp_value < (timer + 2)) && (comp_value > (timer - 10))) { + comp_value = timer + 2; + } + + MXC_RTCTMR->comp[0] = comp_value; + MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; // clear interrupt + MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; // enable the interrupt // Enable wakeup from RTC - MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER | MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0); + MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0; } //****************************************************************************** @@ -213,6 +239,7 @@ inline void lp_ticker_clear_interrupt(void) { MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS; + MXC_PWRSEQ->flags = MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0; } //******************************************************************************
--- a/targets/hal/TARGET_Maxim/TARGET_MAX32610/rtc_api.c Thu May 07 09:15:08 2015 +0100 +++ b/targets/hal/TARGET_Maxim/TARGET_MAX32610/rtc_api.c Mon May 11 08:15:07 2015 +0100 @@ -41,6 +41,8 @@ #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) +#define WINDOW 1000 + static int rtc_inited = 0; static volatile uint32_t overflow_cnt = 0; @@ -50,6 +52,7 @@ static void overflow_handler(void) { MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_OVERFLOW; + MXC_PWRSEQ->flags = MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER; overflow_cnt++; } @@ -69,20 +72,31 @@ // Enable the clock to the RTC MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN; - // 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)lp_ticker_irq_handler); NVIC_EnableIRQ(RTC0_IRQn); NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler); NVIC_EnableIRQ(RTC3_IRQn); - // Enable the RTC - MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; + // Enable wakeup on RTC rollover + MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER; + + /* RTC registers are only reset on a power cycle. Do not reconfigure the RTC + * if it is already running. + */ + if (!(MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_ENABLE)) { + // Set the clock divider + MXC_RTCTMR->prescale = PRESCALE_VAL; + + // Enable the overflow interrupt + MXC_RTCTMR->inten |= MXC_F_RTC_FLAGS_OVERFLOW; + + // Restart the timer from 0 + MXC_RTCTMR->timer = 0; + + // Enable the RTC + MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_ENABLE; + } } //****************************************************************************** @@ -177,30 +191,42 @@ //****************************************************************************** void lp_ticker_set_interrupt(timestamp_t timestamp) { + uint32_t comp_value; + uint64_t curr_ts64; + uint64_t ts64; + // 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 + + curr_ts64 = rtc_read64(); + ts64 = (uint64_t)timestamp | (curr_ts64 & 0xFFFFFFFF00000000ULL); - 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 this event is older than a recent window, it must be in the future + if ((ts64 < (curr_ts64 - WINDOW)) && ((curr_ts64 - WINDOW) < curr_ts64)) { + ts64 += 0x100000000ULL; } - MXC_RTCTMR->comp[0] = (ts64 << SHIFT_AMT) / 1000000; - MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; + uint32_t timer = MXC_RTCTMR->timer; + if (ts64 <= curr_ts64) { + // This event has already occurred. Set the alarm to expire immediately. + comp_value = timer + 1; + } else { + comp_value = (ts64 << SHIFT_AMT) / 1000000; + } + + // Ensure that the compare value is far enough in the future to guarantee the interrupt occurs. + if ((comp_value < (timer + 2)) && (comp_value > (timer - 10))) { + comp_value = timer + 2; + } + + MXC_RTCTMR->comp[0] = comp_value; + MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; // clear interrupt + MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; // enable the interrupt // Enable wakeup from RTC - MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_RTC_ROLLOVER | MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0); + MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0; } //****************************************************************************** @@ -213,6 +239,7 @@ inline void lp_ticker_clear_interrupt(void) { MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS; + MXC_PWRSEQ->flags = MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0; } //******************************************************************************