From c2fca3dffedfa15044bb70f8a997ea1c3920ebe3 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Fri, 5 Feb 2021 13:13:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DRTC=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E4=BB=A5=E5=8F=8Alibc=20time.c=E5=BA=93=E8=8B=A5=E5=B9=B2?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/libraries/HAL_Drivers/drv_rtc.c | 8 +- components/drivers/rtc/rtc.c | 36 +-- components/libc/compilers/common/sys/time.h | 4 +- components/libc/compilers/common/time.c | 229 +++++++++++--------- 4 files changed, 150 insertions(+), 127 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_rtc.c b/bsp/stm32/libraries/HAL_Drivers/drv_rtc.c index 75f85cfa81..b0dcb8d114 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_rtc.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_rtc.c @@ -6,10 +6,12 @@ * Change Logs: * Date Author Notes * 2018-12-04 balanceTWK first version - * 2020-10-14 Dozingfiretruck Porting for stm32wbxx + * 2020-10-14 Dozingfiretruck Porting for stm32wbxx + * 2021-02-05 Meco Man fix the problem of mixing local time and UTC time */ #include "board.h" +#include #ifdef BSP_USING_ONCHIP_RTC @@ -54,7 +56,7 @@ static time_t get_rtc_timestamp(void) tm_new.tm_year = RTC_DateStruct.Year + 100; LOG_D("get rtc time."); - return mktime(&tm_new); + return timegm(&tm_new); } static rt_err_t set_rtc_time_stamp(time_t time_stamp) @@ -63,7 +65,7 @@ static rt_err_t set_rtc_time_stamp(time_t time_stamp) RTC_DateTypeDef RTC_DateStruct = {0}; struct tm *p_tm; - p_tm = localtime(&time_stamp); + p_tm = gmtime(&time_stamp); if (p_tm->tm_year < 100) { return -RT_ERROR; diff --git a/components/drivers/rtc/rtc.c b/components/drivers/rtc/rtc.c index 682515ce98..c9ba7fb4eb 100644 --- a/components/drivers/rtc/rtc.c +++ b/components/drivers/rtc/rtc.c @@ -11,7 +11,7 @@ * 2018-02-16 armink add auto sync time by NTP */ -#include +#include #include #include @@ -30,7 +30,7 @@ #endif /* RTC_SYNC_USING_NTP */ /** - * Set system date(time not modify). + * Set system date(time not modify, local timezone). * * @param rt_uint32_t year e.g: 2012. * @param rt_uint32_t month e.g: 12 (1~12). @@ -52,10 +52,10 @@ rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) /* lock scheduler. */ rt_enter_critical(); - /* converts calendar time time into local time. */ + /* converts calendar time into local time. */ p_tm = localtime(&now); /* copy the statically located variable */ - memcpy(&tm_new, p_tm, sizeof(struct tm)); + rt_memcpy(&tm_new, p_tm, sizeof(struct tm)); /* unlock scheduler. */ rt_exit_critical(); @@ -64,7 +64,7 @@ rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) tm_new.tm_mon = month - 1; /* tm_mon: 0~11 */ tm_new.tm_mday = day; - /* converts the local time in time to calendar time. */ + /* converts the UTC time into the calendar time. */ now = mktime(&tm_new); device = rt_device_find("rtc"); @@ -80,7 +80,7 @@ rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) } /** - * Set system time(date not modify). + * Set system time(date not modify, local timezone). * * @param rt_uint32_t hour e.g: 0~23. * @param rt_uint32_t minute e.g: 0~59. @@ -102,10 +102,10 @@ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) /* lock scheduler. */ rt_enter_critical(); - /* converts calendar time time into local time. */ + /* converts calendar time into local time. */ p_tm = localtime(&now); /* copy the statically located variable */ - memcpy(&tm_new, p_tm, sizeof(struct tm)); + rt_memcpy(&tm_new, p_tm, sizeof(struct tm)); /* unlock scheduler. */ rt_exit_critical(); @@ -114,7 +114,7 @@ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) tm_new.tm_min = minute; tm_new.tm_sec = second; - /* converts the local time in time to calendar time. */ + /* converts the local time into the calendar time. */ now = mktime(&tm_new); device = rt_device_find("rtc"); @@ -174,6 +174,9 @@ INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init); #include #include +/** + * show date and time (local timezone) + */ void list_date(void) { time_t now; @@ -181,12 +184,15 @@ void list_date(void) now = time(RT_NULL); rt_kprintf("%.*s\n", 25, ctime(&now)); } -FINSH_FUNCTION_EXPORT(list_date, show date and time.) +FINSH_FUNCTION_EXPORT(list_date, show date and time (local timezone)) +FINSH_FUNCTION_EXPORT(set_date, set date(local timezone) e.g: set_date(2010,2,28)) +FINSH_FUNCTION_EXPORT(set_time, set time(local timezone) e.g: set_time(23,59,59)) -FINSH_FUNCTION_EXPORT(set_date, set date. e.g: set_date(2010,2,28)) -FINSH_FUNCTION_EXPORT(set_time, set time. e.g: set_time(23,59,59)) #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) +/** + * get date and time or set (local timezone) [year month day hour min sec] + */ static void date(uint8_t argc, char **argv) { if (argc == 1) @@ -246,9 +252,9 @@ static void date(uint8_t argc, char **argv) rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); } } -MSH_CMD_EXPORT(date, get date and time or set [year month day hour min sec]); -#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ +MSH_CMD_EXPORT(list_date, show date and time (local timezone)) +MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) +#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ #endif /* RT_USING_FINSH */ - #endif /* RT_USING_RTC */ diff --git a/components/libc/compilers/common/sys/time.h b/components/libc/compilers/common/sys/time.h index 28a977c1f9..e99fd7d54f 100644 --- a/components/libc/compilers/common/sys/time.h +++ b/components/libc/compilers/common/sys/time.h @@ -48,8 +48,8 @@ struct timezone { int tz_dsttime; /* type of dst correction */ }; -int gettimeofday(struct timeval *tp, void *ignore); -struct tm *gmtime_r(const time_t *timep, struct tm *r); +int gettimeofday(struct timeval *tp, struct timezone *tz); +time_t timegm(struct tm * const t); #ifdef __cplusplus } diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 99dab71eb4..e2dae1feaf 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -7,13 +7,21 @@ * Date Author Notes * 2019-08-21 zhangjun copy from minilibc * 2020-09-07 Meco Man combine gcc armcc iccarm + * 2021-02-05 Meco Man add timegm() */ #include #include +#ifdef RT_USING_DEVICE +#include +#endif + #if !defined (__IAR_SYSTEMS_ICC__) +/* seconds per day */ +#define SPD 24*60*60 + /* days per month -- nonleap! */ const short __spm[13] = { @@ -34,10 +42,7 @@ const short __spm[13] = static const char days[] = "Sun Mon Tue Wed Thu Fri Sat "; static const char months[] = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec "; -/* seconds per day */ -#define SPD 24*60*60 - -int __isleap(int year) +static int __isleap(int year) { /* every fourth year is a leap year except for century years that are * not divisible by 400. */ @@ -45,6 +50,12 @@ int __isleap(int year) return (!(year % 4) && ((year % 100) || !(year % 400))); } +static void num2str(char *c, int i) +{ + c[0] = i / 10 + '0'; + c[1] = i % 10 + '0'; +} + struct tm *gmtime_r(const time_t *timep, struct tm *r) { time_t i; @@ -87,10 +98,15 @@ struct tm* gmtime(const time_t* t) return gmtime_r(t, &tmp); } -/*TODO timezone is not supprt now */ +/*TODO: timezone */ struct tm* localtime_r(const time_t* t, struct tm* r) { - return gmtime_r(t, r); + time_t local_tz; + int timezone; + + timezone = 0 * 3600 * 8; /* GTM: UTC+0 */ + local_tz = *t + timezone; + return gmtime_r(&local_tz, r); } struct tm* localtime(const time_t* t) @@ -99,84 +115,10 @@ struct tm* localtime(const time_t* t) return localtime_r(t, &tmp); } +/* TODO: timezone */ time_t mktime(struct tm * const t) { - register time_t day; - register time_t i; - register time_t years = t->tm_year - 70; - - if (t->tm_sec > 60) - { - t->tm_min += t->tm_sec / 60; - t->tm_sec %= 60; - } - if (t->tm_min > 60) - { - t->tm_hour += t->tm_min / 60; - t->tm_min %= 60; - } - if (t->tm_hour > 24) - { - t->tm_mday += t->tm_hour / 24; - t->tm_hour %= 24; - } - if (t->tm_mon > 12) - { - t->tm_year += t->tm_mon / 12; - t->tm_mon %= 12; - } - while (t->tm_mday > __spm[1 + t->tm_mon]) - { - if (t->tm_mon == 1 && __isleap(t->tm_year + 1900)) - { - --t->tm_mday; - } - t->tm_mday -= __spm[t->tm_mon]; - ++t->tm_mon; - if (t->tm_mon > 11) - { - t->tm_mon = 0; - ++t->tm_year; - } - } - - if (t->tm_year < 70) - return (time_t) - 1; - - /* Days since 1970 is 365 * number of years + number of leap years since 1970 */ - day = years * 365 + (years + 1) / 4; - - /* After 2100 we have to substract 3 leap years for every 400 years - This is not intuitive. Most mktime implementations do not support - dates after 2059, anyway, so we might leave this out for it's - bloat. */ - if (years >= 131) - { - years -= 131; - years /= 100; - day -= (years >> 2) * 3 + 1; - if ((years &= 3) == 3) - years--; - day -= years; - } - - day += t->tm_yday = __spm[t->tm_mon] + t->tm_mday - 1 + - (__isleap(t->tm_year + 1900) & (t->tm_mon > 1)); - - /* day is now the number of days since 'Jan 1 1970' */ - i = 7; - t->tm_wday = (day + 4) % i; /* Sunday=0, Monday=1, ..., Saturday=6 */ - - i = 24; - day *= i; - i = 60; - return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec; -} - -static void num2str(char *c, int i) -{ - c[0] = i / 10 + '0'; - c[1] = i % 10 + '0'; + return timegm(t); } char* asctime_r(const struct tm *t, char *buf) @@ -213,28 +155,6 @@ char* ctime(const time_t *timep) #endif /* __IAR_SYSTEMS_ICC__ */ -int gettimeofday(struct timeval *tp, void *ignore) -{ - time_t time = 0; -#ifdef RT_USING_DEVICE - rt_device_t device; - device = rt_device_find("rtc"); - RT_ASSERT(device != RT_NULL); - rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); - if (tp != RT_NULL) - { - tp->tv_sec = time; - tp->tv_usec = 0; - } -#else - tv->tv_sec = 0; - tv->tv_usec = 0; -#endif - - return time; -} - - /** * Returns the current time. * @@ -243,15 +163,14 @@ int gettimeofday(struct timeval *tp, void *ignore) * @return time_t return timestamp current. * */ -/* for IAR 6.2 later Compiler */ -#if defined (__IAR_SYSTEMS_ICC__) && (__VER__) >= 6020000 +#if defined (__IAR_SYSTEMS_ICC__) && (__VER__) >= 6020000 /* for IAR 6.2 later Compiler */ #pragma module_name = "?time" #if _DLIB_TIME_USES_64 time_t __time64(time_t *t) #else time_t __time32(time_t *t) #endif -#else +#else /* Keil & GCC */ time_t time(time_t *t) #endif { @@ -290,3 +209,99 @@ RT_WEAK clock_t clock(void) { return rt_tick_get(); } + +/* TODO: timezone */ +int gettimeofday(struct timeval *tp, struct timezone *tz) +{ + time_t time = 0; +#ifdef RT_USING_DEVICE + rt_device_t device; + device = rt_device_find("rtc"); + RT_ASSERT(device != RT_NULL); + rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); + if (tp != RT_NULL) + { + tp->tv_sec = time; + tp->tv_usec = 0; + } +#else + tv->tv_sec = 0; + tv->tv_usec = 0; +#endif + + return time; +} + +time_t timegm(struct tm * const t) +{ + register time_t day; + register time_t i; + register time_t years = t->tm_year - 70; + + if (t->tm_sec > 60) + { + t->tm_min += t->tm_sec / 60; + t->tm_sec %= 60; + } + if (t->tm_min > 60) + { + t->tm_hour += t->tm_min / 60; + t->tm_min %= 60; + } + if (t->tm_hour > 24) + { + t->tm_mday += t->tm_hour / 24; + t->tm_hour %= 24; + } + if (t->tm_mon > 12) + { + t->tm_year += t->tm_mon / 12; + t->tm_mon %= 12; + } + while (t->tm_mday > __spm[1 + t->tm_mon]) + { + if (t->tm_mon == 1 && __isleap(t->tm_year + 1900)) + { + --t->tm_mday; + } + t->tm_mday -= __spm[t->tm_mon]; + ++t->tm_mon; + if (t->tm_mon > 11) + { + t->tm_mon = 0; + ++t->tm_year; + } + } + + if (t->tm_year < 70) + return (time_t) - 1; + + /* Days since 1970 is 365 * number of years + number of leap years since 1970 */ + day = years * 365 + (years + 1) / 4; + + /* After 2100 we have to substract 3 leap years for every 400 years + This is not intuitive. Most mktime implementations do not support + dates after 2059, anyway, so we might leave this out for it's + bloat. */ + if (years >= 131) + { + years -= 131; + years /= 100; + day -= (years >> 2) * 3 + 1; + if ((years &= 3) == 3) + years--; + day -= years; + } + + day += t->tm_yday = __spm[t->tm_mon] + t->tm_mday - 1 + + (__isleap(t->tm_year + 1900) & (t->tm_mon > 1)); + + /* day is now the number of days since 'Jan 1 1970' */ + i = 7; + t->tm_wday = (day + 4) % i; /* Sunday=0, Monday=1, ..., Saturday=6 */ + + i = 24; + day *= i; + i = 60; + return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec; +} -- GitLab