#include #include #include //#include "gd32e10x.h" //#include "gd32e103v_eval.h" #include "Gd32f30x_rtc.h" #include "Gd32f30x_bkp.h" #include "qws_status.h" #include "shark_rtc.h" #include "FreeRTOS.h" #include "task.h" #include "shark_bkp.h" #define IS_LEAP_YEAR(year) ((year % 4 == 0) && ( year % 100 != 0) || (year % 400 == 0)) static uint32_t time_ticks = 0; #define POWER_FIRSTFLAG_REG BKP_DATA_0 #define POWER_FIRSTFLAG_VALUE 0x5AA5 unsigned char check_rtc_time() { int rtcTime = rtc_counter_get(); if(rtcTime > YEAR_20171201_UTS && rtcTime < YEAR_20571201_UTS) return 1; start_uptade_local_time(); return 0; } uint32_t app_getcurrtime_utc(void) { if(check_rtc_time() == 1) return shark_rtc_get_timestamp(); else return 0; } /* get the utc readable time */ void shark_rtc_get_local_time(uint32_t second, time_val *out){ struct tm *tm; tm = localtime((time_t *)&second); out->year = tm->tm_year + 1900; out->month = tm->tm_mon + 1; out->day = tm->tm_mday; out->hour = tm->tm_hour; out->minute = tm->tm_min; out->second = tm->tm_sec; } /* get utc timestamp --> second */ uint32_t shark_rtc_get_timestamp(void){ return rtc_counter_get(); } /*tz quarter-hour ,15min ,-48~+48*/ uint32_t shark_rtc_get_timestamp_with_time_zone(int8_t tz){ return (rtc_counter_get()+ tz*15*60); } void shark_rtc_getcurrtime_loca_time(time_val*ltc) { if(ltc==NULL) return; shark_rtc_get_local_time(shark_rtc_get_timestamp_with_time_zone(qws_status_get()->bike.qws_TZ ),ltc); } /* get utc timestamp --> macro second */ uint64_t shark_rtc_get_timestamp_ms(void){ return (uint64_t)rtc_counter_get() * 1000 + ((xTaskGetTickCount() - time_ticks) / portTICK_RATE_MS)%(1000/portTICK_RATE_MS); } /* set rtc time, used utc timestamp, can not include time zone*/ uint32_t calendar_to_utc(time_val *time){ struct tm utc_time; struct tm my_time; memset(&utc_time, 0, sizeof (struct tm)); memset(&my_time, 0, sizeof (struct tm)); my_time.tm_mday = time->day; my_time.tm_mon = time->month- 1; my_time.tm_year = time->year - 1900; my_time.tm_hour = time->hour; my_time.tm_min = time->minute; my_time.tm_sec = time->second; utc_time.tm_mday = 1; utc_time.tm_mon = 1 - 1; utc_time.tm_year = 1970 - 1900; utc_time.tm_hour = 0; utc_time.tm_min = 0; utc_time.tm_sec = 0; return mktime(&my_time) - mktime(&utc_time); } void shark_rtc_set_time(time_val *time){ uint32_t second = calendar_to_utc(time); /* wait until last write operation on RTC registers has finished */ rtc_lwoff_wait(); /* change the current time */ rtc_counter_set(second); rtc_lwoff_wait(); } void shark_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 shark_rtc_first_init(void){ //keep rtc running and inited while chip reset if (shark_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 shark_rtc_enable_second_irq(int enable){ if (enable){ nvic_irq_enable(RTC_IRQn, 2U, 0U); }else{ nvic_irq_disable(RTC_IRQn); } } void shark_rtc_init(void){ shark_rtc_first_init(); nvic_irq_enable(RTC_Alarm_IRQn , 2U, 0U); exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_RISING); exti_flag_clear(EXTI_17); exti_interrupt_enable(EXTI_17); shark_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; current_count = rtc_counter_get(); //rtc_lwoff_wait(); rtc_alarm_config(current_count + sencod); return rtc_lwoff_wait_timeout(); } int shark_rtc_start_alarm(uint32_t second){ rtc_lwoff_wait(); rtc_interrupt_enable(RTC_INT_ALARM);// second means a shot here rtc_lwoff_wait(); rtc_flag_clear(RTC_INT_SECOND ); //RTC_INT_FLAG_SECOND rtc_lwoff_wait(); rtc_interrupt_disable(RTC_INT_SECOND); rtc_lwoff_wait(); return set_rtc_alarm(second); } void shark_rtc_stop_alarm(void){ rtc_lwoff_wait(); rtc_interrupt_disable(RTC_INT_ALARM); rtc_lwoff_wait(); rtc_interrupt_enable(RTC_INT_SECOND); rtc_lwoff_wait(); } void shark_rtc_update_alarm(uint32_t sencod){ set_rtc_alarm(sencod); } uint32_t qws_rtc_irq_times = 0; static alarm_handler s_handler = NULL; void shark_rtc_set_alarm_handler(alarm_handler handler){ s_handler = handler; } void RTC_Alarm_IRQHandler(void) { if (rtc_flag_get(RTC_INT_ALARM) != RESET) { /* clear the RTC second interrupt flag*/ rtc_flag_clear(RTC_INT_ALARM); if (s_handler != NULL){ s_handler(); } qws_rtc_irq_times++; } exti_interrupt_flag_clear(EXTI_17); } void RTC_IRQHandler(void){ if (rtc_flag_get(RTC_INT_OVERFLOW /*RTC_INT_FLAG_OVERFLOW*/) != RESET) { /* clear the RTC overflow interrupt flag*/ rtc_flag_clear(RTC_INT_OVERFLOW); } if (rtc_flag_get(RTC_INT_SECOND) != RESET) { time_ticks = xTaskGetTickCount(); /* clear the RTC second interrupt flag*/ rtc_flag_clear(RTC_INT_SECOND); } }