void lp_ticker_set_interrupt(timestamp_t timestamp) { uint64_t timestamp_ticks; uint64_t current_ticks = RTC_CounterGet(); timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)); /* calculate offset value */ timestamp_t offset = timestamp - current_time; if(offset > 0xEFFFFFFF) offset = 100; /* map offset to RTC value */ // ticks = offset * RTC frequency div 1000000 timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000; timestamp_ticks += current_ticks; /* RTC has 24 bit resolution */ timestamp_ticks &= 0xFFFFFF; /* check for RTC limitation */ if((timestamp_ticks - RTC_CounterGet()) >= 0x800000) timestamp_ticks = RTC_CounterGet() + 2; /* Set callback */ RTC_FreezeEnable(true); RTC_CompareSet(0, (uint32_t)timestamp_ticks); RTC_IntEnable(RTC_IF_COMP0); RTC_FreezeEnable(false); }
/****************************************************************************** * @brief Main function *****************************************************************************/ int main(void) { /* Initialize chip */ CHIP_Init(); /* Enable code view */ setupSWO(); /* Initialize LCD */ SegmentLCD_Init(false); /* Enable the HFPER clock */ CMU_ClockEnable(cmuClock_HFPER, true); /* Configure RTC and GPIO */ rtc_setup(); gpio_setup(); /* Stay in this loop forever */ while (1) { /* Wait for Push Button 1 to be pressed */ while (GPIO_PinInGet(PB0_PORT, PB0_PIN)) ; /* and released, so that we do not exit the while loop below immediately */ while (!GPIO_PinInGet(PB0_PORT, PB0_PIN)) ; /* Reset time */ time = 0; /* Disable LCD */ LCD_Enable(true); /* Update time until Push Button 1 is pressed again */ while (1) { if (RTC_CounterGet() == 0) { SegmentLCD_Number(++time); } if (!GPIO_PinInGet(PB0_PORT, PB0_PIN)) break; } /* Delay while showing the result on the LCD */ for (uint32_t delay = 0; delay < 30; delay++) { /* Wait for the RTC to overflow once */ while (RTC_CounterGet() != 0) ; while (RTC_CounterGet() == 0) ; } /* Disable LCD */ LCD_Enable(false); } }
void os_idle_demon(void) { RTC_Init_TypeDef init; unsigned int sleep; /* The idle demon is a system thread, running when no other thread is */ /* ready to run. */ /* Enable system clock for RTC */ /* LFXO setup */ /* Use 70% boost */ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOBOOST_MASK) | CMU_CTRL_LFXOBOOST_70PCENT; /* Ensure LE modules are accessible */ CMU_ClockEnable(cmuClock_CORELE, true); /* Enable osc as LFACLK in CMU (will also enable oscillator if not enabled) */ CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); /* Use a 32 division prescaler to reduce power consumption. */ CMU_ClockDivSet(cmuClock_RTC, cmuClkDiv_32); /* Enable clock to RTC module */ CMU_ClockEnable(cmuClock_RTC, true); init.enable = false; init.debugRun = false; init.comp0Top = false; /* Count to max value before wrapping */ RTC_Init(&init); /* Disable interrupt generation from RTC0 */ RTC_IntDisable(_RTC_IF_MASK); /* Enable interrupts */ NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_EnableIRQ(RTC_IRQn); for (;;) { /* os_suspend stops scheduler and returns time to next event in OS_TICK units */ sleep = os_suspend(); if (sleep) { RTC_CompareSet(0, sleep - 1); RTC_IntClear(RTC_IFC_COMP0); RTC_IntEnable(RTC_IF_COMP0); RTC_CounterReset(); /* Enter EM2 low power mode - could be replaced with EM1 if required */ EMU_EnterEM2(true); /* get information how long we were in sleep */ sleep = RTC_CounterGet(); RTC_Enable(false); }; /* resume scheduler providing information how long MCU was sleeping */ os_resume(sleep); } }
timestamp_t lp_ticker_read() { uint64_t ticks_temp; uint64_t ticks = RTC_CounterGet(); /* ticks = counter tick value * timestamp = value in microseconds * timestamp = ticks * 1.000.000 / RTC frequency */ ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT); return (timestamp_t) (ticks_temp & 0xFFFFFFFF); }
/******************************************************************//** * @brief * Configure RTC device * * @details * * @note * * @param[in] dev * Pointer to device descriptor * * @param[in] cmd * RTC control command * * @param[in] args * Arguments * * @return * Error code *********************************************************************/ static rt_err_t rt_rtc_control(rt_device_t dev, rt_uint8_t cmd, void *args) { RT_ASSERT(dev != RT_NULL); switch (cmd) { case RT_DEVICE_CTRL_RTC_GET_TIME: *(rt_uint32_t *)args = rtc_time + RTC_CounterGet(); break; case RT_DEVICE_CTRL_RTC_SET_TIME: { rtc_time = *(rt_uint32_t *)args; /* Reset counter */ RTC_Enable(false); RTC_Enable(true); } break; } return RT_EOK; }
timestamp_t lp_ticker_read() { return (timestamp_t) RTC_CounterGet(); }
/**************************************************************************//** * @brief vPortSuppressTicksAndSleep * Override the default definition of vPortSuppressTicksAndSleep() that is weakly * defined in the FreeRTOS Cortex-M3 port layer layer *****************************************************************************/ void vPortSuppressTicksAndSleep(portTickType xExpectedIdleTime) { unsigned long ulReloadValue, ulCompleteTickPeriods; unsigned int ulRemainingCounter; portTickType xModifiableIdleTime; /* Make sure the SysTick reload value does not overflow the counter. */ if (xExpectedIdleTime > xMaximumPossibleSuppressedTicks) { xExpectedIdleTime = xMaximumPossibleSuppressedTicks; } /* Calculate the reload value required to wait xExpectedIdleTime * tick periods. */ ulReloadValue = (ulTimerReloadValueForOneTick * (xExpectedIdleTime )); if (ulReloadValue > ulStoppedTimerCompensation) { ulReloadValue -= ulStoppedTimerCompensation; } /* Stop the System Tick momentarily. The time the System Tick is stopped for * is accounted for as best it can be, but using the tickless mode will * inevitably result in some tiny drift of the time maintained by the * kernel with respect to calendar time. */ /* Stop the RTC clock*/ RTC_Enable(false); /* Enter a critical section but don't use the taskENTER_CRITICAL() * method as that will mask interrupts that should exit sleep mode. */ INT_Disable(); /* The tick flag is set to false before sleeping. If it is true when sleep * mode is exited then sleep mode was probably exited because the tick was * suppressed for the entire xExpectedIdleTime period. */ intTickFlag = false; /* If a context switch is pending or a task is waiting for the scheduler * to be unsuspended then abandon the low power entry. */ if (eTaskConfirmSleepModeStatus() == eAbortSleep) { RTC_Enable(true); /* Re-enable interrupts - see comments above __disable_interrupt() * call above. */ INT_Enable(); } else { /* Set the new reload value. */ ulReloadValue -= RTC_CounterGet(); RTC_CompareSet(0, ulReloadValue); /* Restart the counter*/ RTC_CounterReset(); /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can * set its parameter to 0 to indicate that its implementation contains * its own wait for interrupt or wait for event instruction, and so wfi * should not be executed again. However, the original expected idle * time variable must remain unmodified, so a copy is taken. */ xModifiableIdleTime = xExpectedIdleTime; configPRE_SLEEP_PROCESSING(xModifiableIdleTime); if (xModifiableIdleTime > 0) { SLEEP_Sleep(); __DSB(); __ISB(); } configPOST_SLEEP_PROCESSING(xExpectedIdleTime); /* Stop SysTick. Again, the time the SysTick is stopped for is * accounted for as best it can be, but using the tickless mode will * inevitably result in some tiny drift of the time maintained by the * kernel with respect to calendar time. */ /* Store current counter value */ ulRemainingCounter = RTC_CounterGet(); /* Stop the RTC clock*/ RTC_Enable(false); /* Re-enable interrupts */ INT_Enable(); if (intTickFlag != false) { /* The tick interrupt has already executed, * Reset the alarm value with whatever remains of this tick period. */ RTC_CompareSet(0, TIMER_CAPACITY & (ulTimerReloadValueForOneTick - RTC_CounterGet())); /* The tick interrupt handler will already have pended the tick * processing in the kernel. As the pending tick will be * processed as soon as this function exits, the tick value * maintained by the tick is stepped forward by one less than the * time spent waiting. */ ulCompleteTickPeriods = xExpectedIdleTime - 1UL; } else { /* Some other interrupt than system tick ended the sleep. * Calculate how many tick periods passed while the processor * was waiting */ ulCompleteTickPeriods = ulRemainingCounter / ulTimerReloadValueForOneTick; /* The reload value is set to whatever fraction of a single tick * period remains. */ if (ulCompleteTickPeriods == 0) { ulReloadValue = ulTimerReloadValueForOneTick - ulRemainingCounter; } else { ulReloadValue = ulRemainingCounter - (ulCompleteTickPeriods * ulTimerReloadValueForOneTick); } RTC_CompareSet(0, ulReloadValue); } /* Restart the RTCounter */ RTC_CounterReset(); /* The tick forward by the number of tick periods that * remained in a low power state. */ vTaskStepTick(ulCompleteTickPeriods); } }
uint32_t rtt_get_counter(void) { return RTC_CounterGet(); }
/***************************************************************************//** * @brief Get value of RTC counter register in miliseconds ******************************************************************************/ uint32_t RTC_CounterGetMs(void) { return (RTC_CounterGet() * 1000) / RTC_FREQ; }
/*---------------------------------------------------------------------------*/ uint32_t rtc_getvalue(void) { return RTC_CounterGet(); }
/*---------------------------------------------------------------------------*/ rtimer_clock_t rtimer_arch_now(void) { return RTC_CounterGet(); }