uint32_t lp_ticker_get_overflows_counter(void) { // TODO: is there a race condition below if the RTC value changes right after we read it? uint32_t temp = RTC_HAL_GetSecsReg(RTC_BASE) & RTC_OVERFLOW_MASK; while (temp != (RTC_HAL_GetSecsReg(RTC_BASE) & RTC_OVERFLOW_MASK)){ temp = RTC_HAL_GetSecsReg(RTC_BASE) & RTC_OVERFLOW_MASK; } return temp >> RTC_TIMER_BITS; }
uint32_t lp_ticker_read() { if (!lp_ticker_inited) { lp_ticker_init(); } uint32_t temp_pre = RTC_HAL_GetPrescaler(RTC_BASE); // RTC sec might be GT 4095, therfore use modulo the max allowance uint32_t temp_sec = RTC_HAL_GetSecsReg(RTC_BASE) % (1 << RTC_TIMER_BITS); while ((temp_pre != RTC_HAL_GetPrescaler(RTC_BASE)) || (temp_sec != (RTC_HAL_GetSecsReg(RTC_BASE) & RTC_TIMER_MASK))) { temp_pre = RTC_HAL_GetPrescaler(RTC_BASE); temp_sec = RTC_HAL_GetSecsReg(RTC_BASE) & RTC_TIMER_MASK; } return (temp_sec << 15 | temp_pre); }
void lp_ticker_set_interrupt(uint32_t now, uint32_t time) { // On K64F, the compare value can be only set when the LPTMR is disabled // However, disabling the LPTMR will automatically clear the LPTMR counter // So we need to compensate for the time that already passed lp_compare_value = time; uint32_t ticks = time > now ? time - now : (uint32_t)((uint64_t)time + 0xFFFFFFFFu - now); lp_lptmr_schedule_ticks = 0; lp_ticker_lptmr_scheduled_flag = 0; RTC_HAL_EnableCounter(RTC_BASE, false); if (ticks > LPTMR_TIMER_MAX_VALUE) { ticks -= RTC_PRESCALER_MAX_VALUE + 1 - RTC_HAL_GetPrescaler(RTC_BASE); uint32_t seconds = RTC_HAL_GetSecsReg(RTC_BASE); while (ticks > LPTMR_TIMER_MAX_VALUE) { ticks -= RTC_PRESCALER_MAX_VALUE + 1; seconds++; } RTC_HAL_SetAlarmReg(RTC_BASE, seconds); RTC_HAL_SetAlarmIntCmd(RTC_BASE, true); // the lp timer will be triggered once RTC alarm is set lp_lptmr_schedule_ticks = ticks; } else { // restart counter, set compare LPTMR_HAL_Disable(LPTMR0_BASE); LPTMR_HAL_SetCompareValue(LPTMR0_BASE, ticks); LPTMR_HAL_Enable(LPTMR0_BASE); } RTC_HAL_EnableCounter(RTC_BASE, true); }
/*FUNCTION********************************************************************** * * Function Name : RTC_DRV_SetAlarm * Description : sets the RTC alarm. * This function will first check if the date time has correct format. If yes, * convert the date time to seconds, and set the alarm in seconds. * *END**************************************************************************/ bool RTC_DRV_SetAlarm(uint32_t instance, rtc_datetime_t *alarmTime, bool enableAlarmInterrupt) { assert(alarmTime); uint32_t rtcBaseAddr = g_rtcBaseAddr[instance]; uint32_t srcClock = 0; uint32_t alrmSeconds = 0; uint32_t currSeconds = 0; /* Return error if the alarm time provided is not valid */ if (!(RTC_HAL_IsDatetimeCorrectFormat(alarmTime))) { return false; } RTC_HAL_ConvertDatetimeToSecs(alarmTime, &alrmSeconds); /* Get the current time */ currSeconds = RTC_HAL_GetSecsReg(rtcBaseAddr); if ((srcClock = CLOCK_SYS_GetExternalRefClock32kFreq()) != 32768U) { /* As the seconds register will not increment every second, we need to adjust the value * programmed to the alarm register */ alrmSeconds = alrmSeconds / (32768U / srcClock); } /* Make sure the alarm is for a future time */ if (alrmSeconds < currSeconds) { return false; } /* set alarm in seconds*/ RTC_HAL_SetAlarmReg(rtcBaseAddr, alrmSeconds); /* Activate or deactivate the Alarm interrupt based on user choice */ RTC_HAL_SetAlarmIntCmd(rtcBaseAddr, enableAlarmInterrupt); return true; }
time_t rtc_read(void) { return (time_t)RTC_HAL_GetSecsReg(RTC_BASE); }