From 8c4663605238dddc098fb2f7c1c0fc8bdcbb03bd Mon Sep 17 00:00:00 2001 From: wangchen <253227059@qq.com> Date: Sat, 23 Jul 2022 10:30:19 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20M=E6=A0=B8time=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=B0=83=E7=94=A8RTC=E6=8E=A5=E5=8F=A3=20?= =?UTF-8?q?=E3=80=90=E8=83=8C=E6=99=AF=E3=80=91M=E6=A0=B8time=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=94=AF=E6=8C=81=E8=B0=83=E7=94=A8RTC=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【修改方案】 1, 增加注册接口 2, 读写时间时判断是否有rtc 【影响】 对现有的产品编译不会有影响。 re #I5IKMN Signed-off-by: wangchen --- kal/cmsis/cmsis_liteos2.c | 12 ++ kal/libc/newlib/porting/include/time.h | 1 - kal/libc/newlib/porting/src/time.c | 2 +- kal/posix/include/rtc_time_hook.h | 95 ++++++++++++++ kal/posix/src/time.c | 167 ++++++++++++++++++++----- 5 files changed, 242 insertions(+), 35 deletions(-) create mode 100644 kal/posix/include/rtc_time_hook.h diff --git a/kal/cmsis/cmsis_liteos2.c b/kal/cmsis/cmsis_liteos2.c index b8388155..f0c1de21 100644 --- a/kal/cmsis/cmsis_liteos2.c +++ b/kal/cmsis/cmsis_liteos2.c @@ -631,6 +631,12 @@ void osThreadExit(void) UNREACHABLE; } +/* before kernel running osDelay is implemented by HalDelay interface */ +WEAK VOID HalDelay(UINT32 ticks) +{ + +} + osStatus_t osDelay(uint32_t ticks) { UINT32 ret; @@ -640,6 +646,12 @@ osStatus_t osDelay(uint32_t ticks) if (ticks == 0) { return osErrorParameter; } + + if (osKernelGetState() != osKernelRunning) { + HalDelay(ticks); + return osOK; + } + ret = LOS_TaskDelay(ticks); if (ret == LOS_OK) { return osOK; diff --git a/kal/libc/newlib/porting/include/time.h b/kal/libc/newlib/porting/include/time.h index 9632d6c8..66b7b268 100644 --- a/kal/libc/newlib/porting/include/time.h +++ b/kal/libc/newlib/porting/include/time.h @@ -31,7 +31,6 @@ #ifndef _ADAPT_TIME_H #define _ADAPT_TIME_H -#define _timezone timezone #define __TM_GMTOFF __tm_gmtoff #define __TM_ZONE __tm_zone diff --git a/kal/libc/newlib/porting/src/time.c b/kal/libc/newlib/porting/src/time.c index 2eb2a6b2..7213fce1 100644 --- a/kal/libc/newlib/porting/src/time.c +++ b/kal/libc/newlib/porting/src/time.c @@ -47,7 +47,7 @@ int _gettimeofday(struct timeval *__tp, void *__tzp) __tp->tv_usec = ts.tv_nsec / OS_SYS_NS_PER_US; } if (tz != NULL) { - tz->tz_minuteswest = timezone / SECS_PER_MIN; + tz->tz_minuteswest = _timezone / SECS_PER_MIN; tz->tz_dsttime = 0; } return 0; diff --git a/kal/posix/include/rtc_time_hook.h b/kal/posix/include/rtc_time_hook.h new file mode 100644 index 00000000..0b8eb5bc --- /dev/null +++ b/kal/posix/include/rtc_time_hook.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTC_TIME_HOOK_H +#define _RTC_TIME_HOOK_H + +#include "los_config.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + + +/* + * RTC interfaces for improving the accuracy of the time, need implement and + * register by user, implementation method is as follows: + * + * UINT64 RtcGetTickHook(VOID) + * brief: supplement expanded ticks + * input: VOID + * return: UINT64 ticks + * + * INT32 RtcGetTimeHook(UINT64 *usec) + * brief: get RTC time + * output: UINT64 *usec, pointer to get the time, value is counted in microsecond(us) + * return: non-0 if error, 0 if success. + * + * INT32 RtcSetTimeHook(UINT64 msec, UINT64 *usec) + * brief: set RTC time + * input: UINT64 msec, the time to be set counted in millisecond(ms). + * input: UINT64 *usec, the time to be set counted in microsecond(us) + * return: non-0 if error, 0 if success. + * + * INT32 RtcGetTimezoneHook(INT32 *tz) + * brief: get RTC timezone + * output: INT32 *tz, pointer to get the timezone, value is counted in second + * return: non-0 if error, 0 if success. + * + * INT32 RtcSetTimezoneHook(INT32 tz) + * brief: set RTC timezone + * input: INT32 tz, the timezone to be set, value is counted in second + * return: non-0 if error, 0 if success. + */ +struct RtcTimeHook { + UINT64 (*RtcGetTickHook)(VOID); + INT32 (*RtcGetTimeHook)(UINT64 *usec); + INT32 (*RtcSetTimeHook)(UINT64 msec, UINT64 *usec); + INT32 (*RtcGetTimezoneHook)(INT32 *tz); + INT32 (*RtcSetTimezoneHook)(INT32 tz); +}; + +/* + * @brief let user register a RTC getter hook to improve time accuracy for time-related POSIX methods. + * @param cfg, a structure, member is pointer to function to be registered + * @return VOID. + */ +VOID LOS_RtcHookRegister(struct RtcTimeHook *cfg); + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/kal/posix/src/time.c b/kal/posix/src/time.c index 7d183703..72b994f0 100644 --- a/kal/posix/src/time.c +++ b/kal/posix/src/time.c @@ -1,6 +1,5 @@ /* - * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -44,6 +43,7 @@ #include "los_context.h" #include "los_interrupt.h" #include "sys/times.h" +#include "rtc_time_hook.h" #define DELAYTIMER_MAX 0x7FFFFFFFF @@ -61,12 +61,38 @@ STATIC const UINT16 g_daysInMonth[2][13] = { STATIC const UINT8 g_montbl[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; #endif +#ifndef __USE_NEWLIB__ +#define g_timezone timezone +#else +#define g_Timezone _timezone +#endif + /* * Time zone information, stored in seconds, * negative values indicate the east of UTC, * positive values indicate the west of UTC. */ -long timezone = -8 * 60 * 60; // defaults to CST: 8 hours east of the Prime Meridian +long g_timezone = -8 * 60 * 60; // set default to CST(UTC+8) + +/* + * store register rtc func + */ +STATIC struct RtcTimeHook g_rtcTimeFunc; + +STATIC UINT64 g_rtcTimeBase = 0; +STATIC UINT64 g_systickBase = 0; + +VOID LOS_RtcHookRegister(struct RtcTimeHook *cfg) +{ + if (cfg == NULL) { + return; + } + g_rtcTimeFunc.RtcGetTickHook = cfg->RtcGetTickHook; + g_rtcTimeFunc.RtcGetTimeHook = cfg->RtcGetTimeHook; + g_rtcTimeFunc.RtcSetTimeHook = cfg->RtcSetTimeHook; + g_rtcTimeFunc.RtcGetTimezoneHook = cfg->RtcGetTimezoneHook; + g_rtcTimeFunc.RtcSetTimezoneHook = cfg->RtcSetTimezoneHook; +} int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { @@ -443,6 +469,10 @@ int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct clock_t clock(void) { + if (g_rtcTimeFunc.RtcGetTickHook != NULL) { + return g_rtcTimeFunc.RtcGetTickHook(); + } + clock_t clk; struct timespec hwTime; OsGetHwTime(&hwTime); @@ -453,19 +483,52 @@ clock_t clock(void) return clk; } +STATIC UINT64 GetCurrentTime(VOID) +{ + UINT64 tickDelta = 0; + UINT64 currentTick; + + if (g_rtcTimeFunc.RtcGetTickHook != NULL) { + currentTick = g_rtcTimeFunc.RtcGetTickHook(); + if ((g_systickBase != 0) && (currentTick > g_systickBase)) { + tickDelta = currentTick - g_systickBase; + } + } + return g_rtcTimeBase + LOS_Tick2MS((UINT32)tickDelta); +} + time_t time(time_t *timer) { - struct timespec ts; + UINT64 usec = 0; + time_t sec; + INT32 rtcRet = 0; - if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) { - return (time_t)-1; - } + if (g_rtcTimeFunc.RtcGetTimeHook != NULL) { + rtcRet = g_rtcTimeFunc.RtcGetTimeHook(&usec); + if (rtcRet != 0) { + UINT64 currentTime; + currentTime = GetCurrentTime(); + sec = currentTime / OS_SYS_MS_PER_SECOND; + } else { + sec = usec / OS_SYS_US_PER_SECOND; + } + if (timer != NULL) { + *timer = sec; + } + return sec; + } else { + struct timespec ts; + if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) { + return (time_t)-1; + } - if (timer != NULL) { - *timer = ts.tv_sec; + if (timer != NULL) { + *timer = ts.tv_sec; + } + return ts.tv_sec; } - return ts.tv_sec; } + #ifndef __USE_NEWLIB__ /* * Compute the `struct tm' representation of T, @@ -558,7 +621,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) errno = EFAULT; return NULL; } - if (!ConvertSecs2Utc(*timep, -timezone, result)) { + if (!ConvertSecs2Utc(*timep, -g_timezone, result)) { errno = EINVAL; return NULL; } @@ -633,18 +696,42 @@ time_t mktime(struct tm *tmptr) int gettimeofday(struct timeval *tv, void *ptz) { - struct timespec ts; struct timezone *tz = (struct timezone *)ptz; if (tv != NULL) { - if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) { - return -1; + INT32 rtcRet; + UINT64 usec = 0; + UINT64 currentTime; + + if (g_rtcTimeFunc.RtcGetTimeHook != NULL) { + rtcRet = g_rtcTimeFunc.RtcGetTimeHook(&usec); + if (rtcRet != 0) { + currentTime = GetCurrentTime(); + tv->tv_sec = currentTime / OS_SYS_MS_PER_SECOND; + tv->tv_usec = (currentTime % OS_SYS_MS_PER_SECOND) * OS_SYS_MS_PER_SECOND; + } else { + tv->tv_sec = usec / OS_SYS_US_PER_SECOND; + tv->tv_usec = usec % OS_SYS_US_PER_SECOND; + } + } else { + struct timespec ts; + if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) { + return -1; + } + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / OS_SYS_NS_PER_US; } - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / OS_SYS_NS_PER_US; } + if (tz != NULL) { - tz->tz_minuteswest = timezone / SECS_PER_MIN; + INT32 timeZone = 0; + if (g_rtcTimeFunc.RtcGetTimezoneHook != NULL) { + g_rtcTimeFunc.RtcGetTimezoneHook(&timeZone); + tz->tz_minuteswest = timezone / SECS_PER_MIN; + } else { + tz->tz_minuteswest = g_timezone / SECS_PER_MIN; + } + tz->tz_dsttime = 0; } return 0; @@ -654,34 +741,49 @@ int gettimeofday(struct timeval *tv, void *ptz) int settimeofday(const struct timeval *tv, const struct timezone *tz) { struct timespec ts; - INT32 rtcTimeZone = timezone; if (tv == NULL) { errno = EFAULT; return -1; } - if (tz != NULL) { - if ((tz->tz_minuteswest >= TIME_ZONE_MIN) && - (tz->tz_minuteswest <= TIME_ZONE_MAX)) { - rtcTimeZone = tz->tz_minuteswest * SECS_PER_MIN; - } else { - errno = EINVAL; - return -1; - } - } if (tv->tv_usec >= OS_SYS_US_PER_SECOND) { errno = EINVAL; return -1; } - ts.tv_sec = tv->tv_sec; - ts.tv_nsec = tv->tv_usec * OS_SYS_NS_PER_US; - if (-1 == clock_settime(CLOCK_REALTIME, &ts)) { - return -1; + if (tz != NULL) { + if ((tz->tz_minuteswest >= TIME_ZONE_MIN) && + (tz->tz_minuteswest <= TIME_ZONE_MAX)) { + g_timezone = tz->tz_minuteswest * SECS_PER_MIN; + } else { + errno = EINVAL; + return -1; + } + + if (g_rtcTimeFunc.RtcSetTimezoneHook != NULL) { + g_rtcTimeFunc.RtcSetTimezoneHook(g_timezone); + } } - timezone = rtcTimeZone; + if (g_rtcTimeFunc.RtcSetTimeHook != NULL) { + UINT64 usec; + g_rtcTimeBase = tv->tv_sec * OS_SYS_MS_PER_SECOND + tv->tv_usec / OS_SYS_MS_PER_SECOND; + usec = tv->tv_sec * OS_SYS_US_PER_SECOND + tv->tv_usec; + if (-1 == g_rtcTimeFunc.RtcSetTimeHook(g_rtcTimeBase, &usec)) { + return -1; + } + } else { + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec * OS_SYS_NS_PER_US; + if (-1 == clock_settime(CLOCK_REALTIME, &ts)) { + return -1; + } + } + + if (g_rtcTimeFunc.RtcGetTickHook != NULL) { + g_systickBase = g_rtcTimeFunc.RtcGetTickHook(); + } return 0; } @@ -718,4 +820,3 @@ clock_t times(struct tms *tms) } return clockTick; } -