#include <stddef.h>
#include "Sys_Scheduler_Lib.h"
typedef struct
{
uint32_t u32msRocBak;
uint32_t u32Task2msCnt;
uint32_t u32Task5msCnt;
uint32_t u32Task10msCnt;
uint32_t u32Task20msCnt;
uint32_t u32Task50msCnt;
uint32_t u32Task100msCnt;
} Sys_Scheduler_st_t;
typedef struct
{
uint32_t u32Pending;
uint32_t u32usCounter;
Sys_Timer_st_t *pstList;
}Sys_Timer_Ctrl_st_t;
#define SYS_TIMER_MODE_IDLE (0UL)
#define SYS_TIMER_MODE_RUN (1UL)
#define SYS_TIMER_MODE_LOOP (2UL)
uint32_t g_u32SysIntInterval = 0UL;
uint32_t g_u32SysusCounter = 0UL;
volatile uint32_t g_u32SysmsRollingCounter = 0UL;
Sys_Scheduler_st_t g_stSysScheduler;
Sys_Timer_Ctrl_st_t g_stSysTimerCtrl;
uint32_t Sys_Get_ms_Rolling_Counter(void)
{
uint32_t u32Counter[2];
do
{
u32Counter[0] = g_u32SysmsRollingCounter;
u32Counter[1] = g_u32SysmsRollingCounter;
}while (u32Counter[0] != u32Counter[1]);
return u32Counter[0];
}
int32_t Sys_Get_Running_Time(Sys_Time_st_t *pstTime)
{
int32_t i32Result;
uint32_t u32msCounter;
i32Result = -1;
if (pstTime != NULL)
{
u32msCounter = Sys_Get_ms_Rolling_Counter();
pstTime->u32Hour = u32msCounter / 3600000UL;
u32msCounter = u32msCounter % 3600000UL;
pstTime->u32Min = u32msCounter / 60000UL;
u32msCounter = u32msCounter % 60000UL;
pstTime->u32Sec = u32msCounter / 1000UL;
u32msCounter = u32msCounter % 1000UL;
pstTime->u32mSec = u32msCounter;
i32Result = 0;
}
return i32Result;
}
int32_t Sys_Timer_Start(Sys_Timer_st_t *pHandle, uint32_t u32Interval, uint32_t u32Loop, Sys_Timer_Cb_pfn_t pfnCallBack)
{
int32_t i32Result;
uint32_t u32Exist;
Sys_Timer_st_t *pstSearch;
i32Result = -1;
if (pHandle != NULL)
{
pHandle->u32Run = SYS_TIMER_MODE_IDLE;
pHandle->u32Cnt = 0UL;
pHandle->u32Dst = u32Interval;
pHandle->pfnCallBack = pfnCallBack;
if (g_stSysTimerCtrl.pstList == NULL)
{
g_stSysTimerCtrl.u32Pending = 1UL;
pHandle->pstNext = NULL;
g_stSysTimerCtrl.pstList = pHandle;
g_stSysTimerCtrl.u32Pending = 0UL;
}
else if (g_stSysTimerCtrl.pstList == pHandle)
{
/* Nothing to do */
}
else
{
u32Exist = 0UL;
pstSearch = g_stSysTimerCtrl.pstList;
while((pstSearch->pstNext != NULL) && (u32Exist == 0UL))
{
pstSearch = pstSearch->pstNext;
if (pstSearch == pHandle)
{
u32Exist = 1UL;
}
}
if (u32Exist == 0UL)
{
g_stSysTimerCtrl.u32Pending = 1UL;
pHandle->pstNext = NULL;
pstSearch->pstNext = pHandle;
g_stSysTimerCtrl.u32Pending = 0UL;
}
}
if (u32Loop)
{
pHandle->u32Run = SYS_TIMER_MODE_LOOP;
}
else
{
pHandle->u32Run = SYS_TIMER_MODE_RUN;
}
i32Result = 0;
}
return i32Result;
}
int32_t Sys_Timer_Stop(Sys_Timer_st_t *pHandle)
{
int32_t i32Result;
Sys_Timer_st_t *pstSearch;
i32Result = -1;
if (pHandle != NULL)
{
if (g_stSysTimerCtrl.pstList == NULL)
{
/* Nothing to do */
}
else if (g_stSysTimerCtrl.pstList == pHandle)
{
g_stSysTimerCtrl.u32Pending = 1UL;
pHandle->u32Run = SYS_TIMER_MODE_IDLE;
g_stSysTimerCtrl.pstList = pHandle->pstNext;
g_stSysTimerCtrl.u32Pending = 0UL;
i32Result = 0;
}
else
{
pstSearch = g_stSysTimerCtrl.pstList;
while ((pstSearch->pstNext != NULL) && (pstSearch->pstNext != pHandle))
{
pstSearch = pstSearch->pstNext;
}
if (pstSearch->pstNext == pHandle)
{
g_stSysTimerCtrl.u32Pending = 1UL;
pHandle->u32Run = SYS_TIMER_MODE_IDLE;
pstSearch->pstNext = pHandle->pstNext;
g_stSysTimerCtrl.u32Pending = 0UL;
i32Result = 0;
}
}
}
return i32Result;
}
int32_t Sys_Timer_Get_Status(Sys_Timer_st_t *pHandle)
{
int32_t i32Result;
i32Result = -1;
if (pHandle != NULL)
{
if (pHandle->u32Run)
{
i32Result = 1;
}
else
{
i32Result = 0;
}
}
return i32Result;
}
int32_t Sys_Timer_Get_Counter(Sys_Timer_st_t *pHandle, uint32_t *pu32Counter)
{
int32_t i32Result;
volatile uint32_t *pu32Cnt;
uint32_t u32Counter[2];
i32Result = -1;
if ((pHandle != NULL) && (pu32Counter != NULL))
{
pu32Cnt = (volatile uint32_t *)(&pHandle->u32Cnt);
do
{
u32Counter[0] = *pu32Cnt;
u32Counter[1] = *pu32Cnt;
} while (u32Counter[0] != u32Counter[1]);
*pu32Counter = u32Counter[0];
i32Result = 0;
}
return i32Result;
}
void Sys_Scheduler_Start(uint32_t u32SchCycle)
{
g_u32SysIntInterval = u32SchCycle;
g_u32SysusCounter = 0UL;
g_u32SysmsRollingCounter = 0UL;
g_stSysTimerCtrl.u32Pending = 0UL;
g_stSysTimerCtrl.u32usCounter = 0UL;
g_stSysTimerCtrl.pstList = NULL;
g_stSysScheduler.u32msRocBak = Sys_Get_ms_Rolling_Counter();
g_stSysScheduler.u32Task2msCnt = 0UL;
g_stSysScheduler.u32Task10msCnt = 1UL;
g_stSysScheduler.u32Task20msCnt = 3UL;
g_stSysScheduler.u32Task50msCnt = 5UL;
g_stSysScheduler.u32Task100msCnt = 7UL;
}
void Sys_Scheduling_Service(void)
{
uint32_t u32msROC;
uint32_t u32msDelta;
Sys_Pseudo_Real_Time_Tasks();
u32msROC = Sys_Get_ms_Rolling_Counter();
if (u32msROC >= g_stSysScheduler.u32msRocBak)
{
u32msDelta = u32msROC - g_stSysScheduler.u32msRocBak;
}
else
{
u32msDelta = 0xFFFFFFFFUL - g_stSysScheduler.u32msRocBak + u32msROC + 0x00000001UL;
}
g_stSysScheduler.u32msRocBak = u32msROC;
g_stSysScheduler.u32Task2msCnt += u32msDelta;
if (g_stSysScheduler.u32Task2msCnt >= 2UL)
{
g_stSysScheduler.u32Task2msCnt %= 2UL;
Sys_2ms_Tasks();
}
g_stSysScheduler.u32Task5msCnt += u32msDelta;
if (g_stSysScheduler.u32Task5msCnt >= 5UL)
{
g_stSysScheduler.u32Task5msCnt %= 5UL;
Sys_5ms_Tasks();
}
g_stSysScheduler.u32Task10msCnt += u32msDelta;
if (g_stSysScheduler.u32Task10msCnt >= 10UL)
{
g_stSysScheduler.u32Task10msCnt %= 10UL;
Sys_10ms_Tasks();
}
g_stSysScheduler.u32Task20msCnt += u32msDelta;
if (g_stSysScheduler.u32Task20msCnt >= 20UL)
{
g_stSysScheduler.u32Task20msCnt %= 20UL;
Sys_20ms_Tasks();
}
g_stSysScheduler.u32Task50msCnt += u32msDelta;
if (g_stSysScheduler.u32Task50msCnt >= 50UL)
{
g_stSysScheduler.u32Task50msCnt %= 50UL;
Sys_50ms_Tasks();
}
g_stSysScheduler.u32Task100msCnt += u32msDelta;
if (g_stSysScheduler.u32Task100msCnt >= 100UL)
{
g_stSysScheduler.u32Task100msCnt %= 100UL;
Sys_100ms_Tasks();
}
}
void Sys_Scheduler_ISR(void)
{
uint32_t u32msInc;
Sys_Timer_st_t *pstTimer;
Sys_Timer_st_t *pstPrev;
g_u32SysusCounter += g_u32SysIntInterval;
if (g_u32SysusCounter >= 1000UL)
{
u32msInc = g_u32SysusCounter / 1000UL;
g_u32SysusCounter = g_u32SysusCounter % 1000UL;
g_u32SysmsRollingCounter += u32msInc;
}
g_stSysTimerCtrl.u32usCounter += g_u32SysIntInterval;
if (g_stSysTimerCtrl.u32Pending == 0UL)
{
pstPrev = NULL;
pstTimer = g_stSysTimerCtrl.pstList;
while (pstTimer != NULL)
{
if (pstTimer->u32Run)
{
/* if (pstTimer->u32Cnt + u32Interval < 0xFFFFFFFFUL) */
if (pstTimer->u32Cnt < 0xFFFFFFFFUL - g_stSysTimerCtrl.u32usCounter)
{
pstTimer->u32Cnt += g_stSysTimerCtrl.u32usCounter;
}
else
{
pstTimer->u32Cnt = 0xFFFFFFFFUL;
}
if (pstTimer->u32Cnt >= pstTimer->u32Dst)
{
if (pstTimer->u32Run == SYS_TIMER_MODE_RUN)
{
pstTimer->u32Run = SYS_TIMER_MODE_IDLE;
if (pstPrev == NULL)
{
g_stSysTimerCtrl.pstList = pstTimer->pstNext;
}
else
{
pstPrev->pstNext = pstTimer->pstNext;
}
}
else
{
pstTimer->u32Cnt = 0UL;
}
if (pstTimer->pfnCallBack != NULL)
{
pstTimer->pfnCallBack();
}
}
}
pstPrev = pstTimer;
pstTimer = pstTimer->pstNext;
}
g_stSysTimerCtrl.u32usCounter = 0UL;
}
}