Browse Source

Merge pull request #4306 from mysterywolf/rtc

[libc][stm32-driver RTC] 修复RTC驱动以及libc time.c库若干问题
Bernard Xiong 4 years ago
parent
commit
7fc236dddb

+ 5 - 3
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 <sys/time.h>
 
 #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;

+ 21 - 15
components/drivers/rtc/rtc.c

@@ -11,7 +11,7 @@
  * 2018-02-16     armink       add auto sync time by NTP
  */
 
-#include <time.h>
+#include <sys/time.h>
 #include <string.h>
 #include <rtthread.h>
 
@@ -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 local 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 <finsh.h>
 #include <rtdevice.h>
 
+/**
+ * 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 */

+ 2 - 2
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
 }

+ 122 - 107
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 <sys/time.h>
 #include <rtthread.h>
+#ifdef RT_USING_DEVICE
+#include <rtdevice.h>
+#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;
+}