#include #include #include "bsp/bsp_driver.h" #define IS_LEAP_YEAR(year) ((year % 4 == 0) && ( year % 100 != 0) || (year % 400 == 0)) //static uint32_t time_ticks = 0; uint32_t time_ticks = 0; uint32_t rtc_second = 0; #define POWER_FIRSTFLAG_REG BKP_DATA_0 #define POWER_FIRSTFLAG_VALUE 0x5AA5 unsigned char check_rtc_time(void) { int rtcTime = rtc_counter_get(); if(rtcTime > YEAR_20171201_UTS && rtcTime < YEAR_20571201_UTS) return 1; else return 0; } unsigned char check_utc_stamp_valid(uint32_t utc) { if(utc > YEAR_20171201_UTS && utc < YEAR_20571201_UTS) return 1; else return 0; } /* get utc timestamp --> second */ uint32_t rtc_get_timestamp(void){ return rtc_counter_get(); } /* get utc timestamp --> macro second */ uint64_t rtc_get_timestamp_ms(void){ return (uint64_t)rtc_counter_get() * 1000 ; } void rtc_set_time_with_utc_second(uint32_t utc_s){ /* wait until last write operation on RTC registers has finished */ rtc_lwoff_wait(); /* change the current time */ rtc_counter_set(utc_s); rtc_lwoff_wait(); } static void gd32_rtc_first_init(void){ //keep rtc running and inited while chip reset if (gd32_bkp_first_startup()){ /* enable PMU and BKPI clocks */ rcu_periph_clock_enable(RCU_BKPI); rcu_periph_clock_enable(RCU_PMU); /* allow access to BKP domain */ pmu_backup_write_enable(); /* reset backup domain */ bkp_deinit(); rcu_osci_on(RCU_IRC40K); rcu_osci_stab_wait(RCU_IRC40K); /* select RCU_RTCSRC_IRC40K as RTC clock source */ rcu_rtc_clock_config(RCU_RTCSRC_IRC40K); /* enable RTC Clock */ rcu_periph_clock_enable(RCU_RTC); /* wait for RTC registers synchronization */ rtc_register_sync_wait(); /* wait until last write operation on RTC registers has finished */ rtc_lwoff_wait(); rtc_interrupt_enable(RTC_INT_SECOND); /* wait until last write operation on RTC registers has finished */ rtc_lwoff_wait(); //set 1s a tick rtc_prescaler_set(40000-1); /* wait until last write operation on RTC registers has finished */ rtc_lwoff_wait(); bkp_write_data(POWER_FIRSTFLAG_REG, POWER_FIRSTFLAG_VALUE); }else{ /* allow access to BKP domain */ rcu_periph_clock_enable(RCU_PMU); pmu_backup_write_enable(); rcu_osci_on(RCU_IRC40K); rcu_osci_stab_wait(RCU_IRC40K); /* select RCU_RTCSRC_IRC40K as RTC clock source */ rcu_rtc_clock_config(RCU_RTCSRC_IRC40K); /* enable RTC Clock */ rcu_periph_clock_enable(RCU_RTC); /* wait for RTC registers synchronization */ rtc_register_sync_wait(); rtc_lwoff_wait(); /* enable the RTC second and alarm interrupt*/ rtc_interrupt_enable(RTC_INT_SECOND); rtc_lwoff_wait(); } } static void gd32_rtc_enable_second_irq(int enable){ if (enable){ nvic_irq_enable(RTC_IRQn, RTC_IRQ_PRIORITY, 0U); }else{ nvic_irq_disable(RTC_IRQn); } } void gd32_rtc_init(void){ gd32_rtc_first_init(); //3?ˇ§o?ˇ§o?¨¤1??¨¤?RTC alarmˇ§o?3? gd32_rtc_stop_alarm(); #ifdef GD32F30X_CL nvic_irq_disable(RTC_ALARM_IRQn); #else nvic_irq_disable(RTC_Alarm_IRQn); #endif exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_RISING); exti_flag_clear(EXTI_17); exti_interrupt_enable(EXTI_17); gd32_rtc_enable_second_irq(1); } int rtc_lwoff_wait_timeout(void) { int wait_count = 0xffff; /* loop until LWOFF flag is set */ while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){ if (wait_count -- <= 0){ return -1; } } return 0; } static int set_rtc_alarm(uint32_t sencod){ uint32_t current_count=0; do { current_count = rtc_counter_get(); }while(current_count != rtc_counter_get()); rtc_alarm_config(current_count + sencod); return rtc_lwoff_wait_timeout(); } int gd32_rtc_start_alarm(uint32_t second){ #ifdef GD32F30X_CL nvic_irq_enable(RTC_ALARM_IRQn, RTC_IRQ_PRIORITY, 0U); #else nvic_irq_enable(RTC_Alarm_IRQn, RTC_IRQ_PRIORITY, 0U); #endif exti_flag_clear(EXTI_17); exti_interrupt_enable(EXTI_17); rtc_register_sync_wait(); rtc_flag_clear(RTC_FLAG_ALARM); rtc_lwoff_wait(); rtc_interrupt_enable(RTC_INT_ALARM);// second means a shot here rtc_lwoff_wait(); return set_rtc_alarm(second); } void gd32_rtc_stop_alarm(void){ exti_interrupt_disable(EXTI_17); rtc_flag_clear(RTC_FLAG_ALARM); rtc_lwoff_wait(); rtc_interrupt_disable(RTC_INT_ALARM); rtc_lwoff_wait(); } int gd32_rtc_update_alarm(uint32_t sencod){ return set_rtc_alarm(sencod); } uint32_t rtc_irq_times = 0; static alarm_handler s_handler = NULL; void gd32_rtc_set_alarm_handler(alarm_handler handler){ s_handler = handler; } void RTC_Alarm_IRQHandler(void) { if (rtc_flag_get(RTC_FLAG_ALARM) != RESET) { /* clear the RTC second interrupt flag*/ rtc_flag_clear(RTC_FLAG_ALARM); if (s_handler != NULL){ s_handler(); } rtc_irq_times++; } exti_interrupt_flag_clear(EXTI_17); } void RTC_IRQHandler(void){ if (rtc_flag_get(RTC_FLAG_OVERFLOW /*RTC_INT_FLAG_OVERFLOW*/) != RESET) { /* clear the RTC overflow interrupt flag*/ rtc_flag_clear(RTC_FLAG_OVERFLOW); } if (rtc_flag_get(RTC_FLAG_SECOND) != RESET) { rtc_second++; /* clear the RTC second interrupt flag*/ rtc_flag_clear(RTC_FLAG_SECOND); } }