feat: L0支持systick动态调频

Close #I4YXW9
Signed-off-by: zhushengle <zhushengle@huawei.com>
Change-Id: I052fe71e507f76184c8ac5d6349e368494033cde
This commit is contained in:
zhushengle 2022-03-22 09:40:23 +08:00
parent e703376d68
commit 390a488a97
6 changed files with 196 additions and 35 deletions

View File

@ -89,6 +89,8 @@ BOOL OsSchedTaskSwitch(VOID);
LosTaskCB *OsGetTopTask(VOID);
VOID OsSchedTimeConvertFreq(UINT32 oldFreq);
STATIC INLINE UINT64 OsGetCurrSchedTimeCycle(VOID)
{
return LOS_SysCycleGet();

View File

@ -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

View File

@ -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
* <ul>
* <li>None</li>
* </ul>
*
* @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:
* <ul><li>los_tick.h: the header file that contains the API declaration.</li></ul>
* @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
* <ul>
* <li>This function needs to be invoked only when the clock frequency of the system tick timer adjust as a result of
* changing the CPU frequency.</li>
* </ul>
*
* @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:
* <ul><li>los_tick.h: the header file that contains the API declaration.</li></ul>
* @see None
*/
extern UINT32 LOS_SysTickClockFreqAdjust(const SYS_TICK_FREQ_ADJUST_FUNC handler, UINTPTR param);
/**
* @ingroup los_tick
* @brief Obtain the number of Ticks.

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}
/*****************************************************************************