From 390a488a979edfd6c7d997113ba9968d43360904 Mon Sep 17 00:00:00 2001 From: zhushengle Date: Tue, 22 Mar 2022 09:40:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20L0=E6=94=AF=E6=8C=81systick=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E8=B0=83=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close #I4YXW9 Signed-off-by: zhushengle Change-Id: I052fe71e507f76184c8ac5d6349e368494033cde --- kernel/include/los_sched.h | 2 + kernel/include/los_sortlink.h | 10 +++-- kernel/include/los_tick.h | 52 +++++++++++++++++++++++++ kernel/src/los_sched.c | 71 +++++++++++++++++++++++++++-------- kernel/src/los_sortlink.c | 45 +++++++++++++++++----- kernel/src/los_tick.c | 51 ++++++++++++++++++++++--- 6 files changed, 196 insertions(+), 35 deletions(-) diff --git a/kernel/include/los_sched.h b/kernel/include/los_sched.h index 71feb4c2..cab2775a 100644 --- a/kernel/include/los_sched.h +++ b/kernel/include/los_sched.h @@ -89,6 +89,8 @@ BOOL OsSchedTaskSwitch(VOID); LosTaskCB *OsGetTopTask(VOID); +VOID OsSchedTimeConvertFreq(UINT32 oldFreq); + STATIC INLINE UINT64 OsGetCurrSchedTimeCycle(VOID) { return LOS_SysCycleGet(); diff --git a/kernel/include/los_sortlink.h b/kernel/include/los_sortlink.h index dfca4d3a..a4b1d2b5 100644 --- a/kernel/include/los_sortlink.h +++ b/kernel/include/los_sortlink.h @@ -78,9 +78,9 @@ STATIC INLINE VOID OsDeleteNodeSortLink(SortLinkList *sortList) SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME); } -STATIC INLINE UINT64 GetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime, UINT32 tickPrecision) +STATIC INLINE UINT64 GetSortLinkNextExpireTime(SortLinkAttribute *sortHead, UINT64 startTime, UINT32 tickPrecision) { - LOS_DL_LIST *head = &sortHeader->sortLink; + LOS_DL_LIST *head = &sortHead->sortLink; LOS_DL_LIST *list = head->pstNext; if (LOS_ListEmpty(head)) { @@ -103,11 +103,13 @@ STATIC INLINE UINT64 OsGetNextExpireTime(UINT64 startTime, UINT32 tickPrecision) } SortLinkAttribute *OsGetSortLinkAttribute(SortLinkType type); -UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader); +UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHead); VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type); VOID OsDeleteSortLink(SortLinkList *node); UINT64 OsSortLinkGetTargetExpireTime(UINT64 currTime, const SortLinkList *targetSortList); -UINT64 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader); +UINT64 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHead); +VOID OsSortLinkResponseTimeConvertFreq(UINT32 oldFreq); + #ifdef __cplusplus #if __cplusplus diff --git a/kernel/include/los_tick.h b/kernel/include/los_tick.h index 7920c511..4302064c 100644 --- a/kernel/include/los_tick.h +++ b/kernel/include/los_tick.h @@ -261,6 +261,58 @@ UINT32 OsTickTimerInit(VOID); VOID OsTickSysTimerStartTimeSet(UINT64 currTime); +STATIC INLINE UINT64 OsTimeConvertFreq(UINT64 time, UINT32 oldFreq, UINT32 newFreq) +{ + if (oldFreq >= newFreq) { + return (time / (oldFreq / newFreq)); + } + + return (time * (newFreq / oldFreq)); +} + +/** + * @ingroup los_tick + * @brief Adjust the system tick timer clock frequency function hooks. + * + * @par Description: + * This API is used to adjust the system tick timer clock frequency. + * @attention + * + * + * @param param [IN] Function parameters. + * + * @retval 0: Adjust the system tick timer clock frequency failed. + * @retval more than zero: Adjust after the system tick timer clock frequency. + * @par Dependency: + * + * @see None + */ +typedef UINT32 (*SYS_TICK_FREQ_ADJUST_FUNC)(UINTPTR param); + +/** + * @ingroup los_tick + * @brief Adjust the system tick timer clock frequency. + * + * @par Description: + * This API is used to adjust the system tick timer clock frequency. + * @attention + * + * + * @param handler [IN] Adjust the system tick timer clock frequency function hooks. + * @param param [IN] Function parameters. + * + * @retval LOS_OK or Error code. + * @par Dependency: + * + * @see None + */ +extern UINT32 LOS_SysTickClockFreqAdjust(const SYS_TICK_FREQ_ADJUST_FUNC handler, UINTPTR param); + /** * @ingroup los_tick * @brief Obtain the number of Ticks. diff --git a/kernel/src/los_sched.c b/kernel/src/los_sched.c index ed6a6f12..b60b3f4f 100644 --- a/kernel/src/los_sched.c +++ b/kernel/src/los_sched.c @@ -47,10 +47,7 @@ extern "C" { #define OS_PRIORITY_QUEUE_NUM 32 #define PRIQUEUE_PRIOR0_BIT 0x80000000U -#define OS_SCHED_TIME_SLICES ((LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) -#define OS_TIME_SLICE_MIN (INT32)((50 * OS_SYS_NS_PER_US) / OS_NS_PER_CYCLE) /* 50us */ #define OS_TICK_RESPONSE_TIME_MAX LOSCFG_BASE_CORE_TICK_RESPONSE_MAX -#define OS_TICK_RESPONSE_PRECISION (UINT32)((OS_SCHED_MINI_PERIOD * 75) / 100) #if (LOSCFG_BASE_CORE_TICK_RESPONSE_MAX == 0) #error "Must specify the maximum value that tick timer counter supports!" #endif @@ -67,6 +64,11 @@ STATIC UINT32 g_schedResponseID = 0; STATIC UINT16 g_tickIntLock = 0; STATIC UINT64 g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME; +STATIC INT32 g_schedTimeSlice; +STATIC INT32 g_schedTimeSliceMin; +STATIC UINT32 g_schedTickMinPeriod; +STATIC UINT32 g_tickResponsePrecision; + VOID OsSchedResetSchedResponseTime(UINT64 responseTime) { if (responseTime <= g_schedResponseTime) { @@ -87,19 +89,19 @@ STATIC INLINE VOID OsTimeSliceUpdate(LosTaskCB *taskCB, UINT64 currTime) STATIC INLINE VOID OsSchedSetNextExpireTime(UINT32 responseID, UINT64 taskEndTime) { - UINT64 nextResponseTime = 0; + UINT64 nextResponseTime; BOOL isTimeSlice = FALSE; UINT64 currTime = OsGetCurrSchedTimeCycle(); - UINT64 nextExpireTime = OsGetNextExpireTime(currTime, OS_TICK_RESPONSE_PRECISION); + UINT64 nextExpireTime = OsGetNextExpireTime(currTime, g_tickResponsePrecision); /* The response time of the task time slice is aligned to the next response time in the delay queue */ - if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > OS_SCHED_MINI_PERIOD)) { + if ((nextExpireTime > taskEndTime) && ((nextExpireTime - taskEndTime) > g_schedTickMinPeriod)) { nextExpireTime = taskEndTime; isTimeSlice = TRUE; } if ((g_schedResponseTime <= nextExpireTime) || - ((g_schedResponseTime - nextExpireTime) < OS_TICK_RESPONSE_PRECISION)) { + ((g_schedResponseTime - nextExpireTime) < g_tickResponsePrecision)) { return; } @@ -111,8 +113,8 @@ STATIC INLINE VOID OsSchedSetNextExpireTime(UINT32 responseID, UINT64 taskEndTim } nextResponseTime = nextExpireTime - currTime; - if (nextResponseTime < OS_TICK_RESPONSE_PRECISION) { - nextResponseTime = OS_TICK_RESPONSE_PRECISION; + if (nextResponseTime < g_tickResponsePrecision) { + nextResponseTime = g_tickResponsePrecision; } g_schedResponseTime = currTime + OsTickTimerReload(nextResponseTime); } @@ -131,10 +133,10 @@ VOID OsSchedUpdateExpireTime(VOID) isPmMode = OsIsPmMode(); #endif if ((runTask->taskID != g_idleTaskID) && !isPmMode) { - INT32 timeSlice = (runTask->timeSlice <= OS_TIME_SLICE_MIN) ? (INT32)OS_SCHED_TIME_SLICES : runTask->timeSlice; + INT32 timeSlice = (runTask->timeSlice <= g_schedTimeSliceMin) ? g_schedTimeSlice : runTask->timeSlice; endTime = runTask->startTime + timeSlice; } else { - endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; + endTime = OS_SCHED_MAX_RESPONSE_TIME - g_tickResponsePrecision; } OsSchedSetNextExpireTime(runTask->taskID, endTime); } @@ -227,10 +229,10 @@ VOID OsSchedTaskEnQueue(LosTaskCB *taskCB) LOS_ASSERT(!(taskCB->taskStatus & OS_TASK_STATUS_READY)); if (taskCB->taskID != g_idleTaskID) { - if (taskCB->timeSlice > OS_TIME_SLICE_MIN) { + if (taskCB->timeSlice > g_schedTimeSliceMin) { OsSchedPriQueueEnHead(&taskCB->pendList, taskCB->priority); } else { - taskCB->timeSlice = OS_SCHED_TIME_SLICES; + taskCB->timeSlice = g_schedTimeSlice; OsSchedPriQueueEnTail(&taskCB->pendList, taskCB->priority); } OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOREADYSTATE, taskCB); @@ -417,7 +419,44 @@ UINT32 OsTaskNextSwitchTimeGet(VOID) UINT64 OsSchedGetNextExpireTime(UINT64 startTime) { - return OsGetNextExpireTime(startTime, OS_TICK_RESPONSE_PRECISION); + return OsGetNextExpireTime(startTime, g_tickResponsePrecision); +} + +STATIC VOID TaskSchedTimeConvertFreq(UINT32 oldFreq) +{ + for (UINT32 loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { + LosTaskCB *taskCB = (((LosTaskCB *)g_taskCBArray) + loopNum); + if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { + continue; + } + if (taskCB->timeSlice > 0) { + taskCB->timeSlice = (INT32)OsTimeConvertFreq((UINT64)taskCB->timeSlice, oldFreq, g_sysClock); + } else { + taskCB->timeSlice = 0; + } + + if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) { + taskCB->startTime = OsTimeConvertFreq(taskCB->startTime, oldFreq, g_sysClock); + } + } +} + +STATIC VOID SchedTimeBaseInit(VOID) +{ + g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME; + + g_schedTickMinPeriod = g_sysClock / LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI; + g_tickResponsePrecision = (g_schedTickMinPeriod * 75) / 100; /* 75 / 100: minimum accuracy */ + g_schedTimeSlice = (INT32)(((UINT64)g_sysClock * LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT) / OS_SYS_US_PER_SECOND); + g_schedTimeSliceMin = (INT32)(((UINT64)g_sysClock * 50) / OS_SYS_US_PER_SECOND); /* Minimum time slice 50 us */ +} + +VOID OsSchedTimeConvertFreq(UINT32 oldFreq) +{ + SchedTimeBaseInit(); + TaskSchedTimeConvertFreq(oldFreq); + OsSortLinkResponseTimeConvertFreq(oldFreq); + OsSchedUpdateExpireTime(); } UINT32 OsSchedInit(VOID) @@ -434,7 +473,7 @@ UINT32 OsSchedInit(VOID) } OsSortLinkInit(g_taskSortLinkList); - g_schedResponseTime = OS_SCHED_MAX_RESPONSE_TIME; + SchedTimeBaseInit(); return LOS_OK; } @@ -512,7 +551,7 @@ BOOL OsSchedTaskSwitch(VOID) if (newTask->taskID != g_idleTaskID) { endTime = newTask->startTime + newTask->timeSlice; } else { - endTime = OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION; + endTime = OS_SCHED_MAX_RESPONSE_TIME - g_tickResponsePrecision; } if (g_schedResponseID == runTask->taskID) { diff --git a/kernel/src/los_sortlink.c b/kernel/src/los_sortlink.c index 3de403ac..3ef717f3 100644 --- a/kernel/src/los_sortlink.c +++ b/kernel/src/los_sortlink.c @@ -42,15 +42,15 @@ extern "C" { SortLinkAttribute g_taskSortLink; SortLinkAttribute g_swtmrSortLink; -UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader) +UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHead) { - LOS_ListInit(&sortLinkHeader->sortLink); + LOS_ListInit(&sortLinkHead->sortLink); return LOS_OK; } -STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList) +STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHead, SortLinkList *sortList) { - LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; + LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHead->sortLink; if (LOS_ListEmpty(head)) { LOS_ListAdd(head, &sortList->sortLinkNode); @@ -81,19 +81,19 @@ STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLin VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type) { UINT32 intSave; - SortLinkAttribute *sortLinkHeader = NULL; + SortLinkAttribute *sortLinkHead = NULL; if (type == OS_SORT_LINK_TASK) { - sortLinkHeader = &g_taskSortLink; + sortLinkHead = &g_taskSortLink; } else if (type == OS_SORT_LINK_SWTMR) { - sortLinkHeader = &g_swtmrSortLink; + sortLinkHead = &g_swtmrSortLink; } else { LOS_Panic("Sort link type error : %u\n", type); } intSave = LOS_IntLock(); SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK); - OsAddNode2SortLink(sortLinkHeader, node); + OsAddNode2SortLink(sortLinkHead, node); LOS_IntRestore(intSave); } @@ -109,6 +109,31 @@ VOID OsDeleteSortLink(SortLinkList *node) LOS_IntRestore(intSave); } +STATIC INLINE VOID SortLinkNodeTimeUpdate(SortLinkAttribute *sortLinkHead, UINT32 oldFreq) +{ + LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHead->sortLink; + + if (LOS_ListEmpty(head)) { + return; + } + + LOS_DL_LIST *nextNode = head->pstNext; + do { + SortLinkList *listSorted = LOS_DL_LIST_ENTRY(nextNode, SortLinkList, sortLinkNode); + listSorted->responseTime = OsTimeConvertFreq(listSorted->responseTime, oldFreq, g_sysClock); + nextNode = nextNode->pstNext; + } while (nextNode != head); +} + +VOID OsSortLinkResponseTimeConvertFreq(UINT32 oldFreq) +{ + SortLinkAttribute *taskHead = &g_taskSortLink; + SortLinkAttribute *swtmrHead = &g_swtmrSortLink; + + SortLinkNodeTimeUpdate(taskHead, oldFreq); + SortLinkNodeTimeUpdate(swtmrHead, oldFreq); +} + SortLinkAttribute *OsGetSortLinkAttribute(SortLinkType type) { if (type == OS_SORT_LINK_TASK) { @@ -130,9 +155,9 @@ UINT64 OsSortLinkGetTargetExpireTime(UINT64 currTime, const SortLinkList *target return (targetSortList->responseTime - currTime); } -UINT64 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader) +UINT64 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHead) { - LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; + LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHead->sortLink; if (LOS_ListEmpty(head)) { return 0; diff --git a/kernel/src/los_tick.c b/kernel/src/los_tick.c index 37d28fd6..84225846 100644 --- a/kernel/src/los_tick.c +++ b/kernel/src/los_tick.c @@ -48,6 +48,7 @@ LITE_OS_SEC_BSS STATIC UINT64 g_tickTimerStartTime; #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) STATIC UINT64 g_tickTimerBase; +STATIC UINT64 g_oldTickTimerBase; LITE_OS_SEC_TEXT STATIC VOID OsUpdateSysTimeBase(VOID) { @@ -87,20 +88,19 @@ LITE_OS_SEC_TEXT UINT64 LOS_SysCycleGet(VOID) #if (LOSCFG_BASE_CORE_TICK_WTIMER == 1) return g_sysTickTimer->getCycle(NULL); #else - STATIC UINT64 oldSchedTime = 0; UINT32 period = 0; UINT32 intSave = LOS_IntLock(); UINT64 time = g_sysTickTimer->getCycle(&period); UINT64 schedTime = g_tickTimerBase + time; - if (schedTime < oldSchedTime) { + if (schedTime < g_oldTickTimerBase) { /* Turn the timer count */ g_tickTimerBase += period; schedTime = g_tickTimerBase + time; } - LOS_ASSERT(schedTime >= oldSchedTime); + LOS_ASSERT(schedTime >= g_oldTickTimerBase); - oldSchedTime = schedTime; + g_oldTickTimerBase = schedTime; LOS_IntRestore(intSave); return schedTime; #endif @@ -230,6 +230,47 @@ LITE_OS_SEC_TEXT UINT32 LOS_TickTimerRegister(const ArchTickTimer *timer, const return LOS_OK; } +UINT32 LOS_SysTickClockFreqAdjust(const SYS_TICK_FREQ_ADJUST_FUNC handler, UINTPTR param) +{ + UINT32 intSave; + UINT32 freq; + UINT32 oldFreq = g_sysClock; + + if (handler == NULL) { + return LOS_ERRNO_SYS_HOOK_IS_NULL; + } + + intSave = LOS_IntLock(); + g_sysTickTimer->lock(); +#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) + UINT64 currTimeCycle = LOS_SysCycleGet(); +#endif + + freq = handler(param); + if ((freq == 0) || (freq == g_sysClock)) { + g_sysTickTimer->unlock(); + LOS_IntRestore(intSave); + return LOS_ERRNO_SYS_CLOCK_INVALID; + } + + g_sysTickTimer->reload(LOSCFG_BASE_CORE_TICK_RESPONSE_MAX); + g_sysTickTimer->unlock(); + +#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0) + g_tickTimerBase = OsTimeConvertFreq(currTimeCycle, oldFreq, freq); + g_oldTickTimerBase = OsTimeConvertFreq(g_oldTickTimerBase, oldFreq, freq); + g_tickTimerStartTime = OsTimeConvertFreq(g_tickTimerStartTime, oldFreq, freq); +#endif + + g_sysTickTimer->freq = freq; + g_sysClock = g_sysTickTimer->freq; + g_cyclesPerTick = g_sysTickTimer->freq / LOSCFG_BASE_CORE_TICK_PER_SECOND; + OsSchedTimeConvertFreq(oldFreq); + LOS_IntRestore(intSave); + + return LOS_OK; +} + LITE_OS_SEC_TEXT_MINOR VOID OsTickSysTimerStartTimeSet(UINT64 currTime) { g_tickTimerStartTime = currTime; @@ -244,7 +285,7 @@ Return : current tick *****************************************************************************/ LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID) { - return (LOS_SysCycleGet() - g_tickTimerStartTime) / OS_CYCLE_PER_TICK; + return (LOS_SysCycleGet() - g_tickTimerStartTime) / g_cyclesPerTick; } /*****************************************************************************