feat: 内核提供tick timer框架,支持多架构多平台通用化
背景:
当前Arch下tick timer的实现依赖于弱函数机制,三方适配时出错及限制较大,且tick
timer作为内核必须模块,未模块化,当前散落在tick和调度等模块中,且当前存在arch依赖
内核,内核也依赖arch的情况,为了解决上述问题,将tick timer模块化,通过提供tick
timer框架实现内核依赖Arch而Arch不依赖内核,并且可以减少对外暴漏的接口,使得三方
适配时更加明确需要实现的接口。
方案描述:
1.tick timer结构
在kernel_liteos_m/arch/include/los_timer.h,中定义结构:
typedef struct {
UINT32 freq;
INT32 irqNum;
UINT32 (*init)(HWI_PROC_FUNC tickHandler);
UINT64 (*getCycle)(UINT32 *period);
VOID (*reload)(UINT64 time);
VOID (*lock)(VOID);
VOID (*unlock)(VOID);
HWI_PROC_FUNC tickHandler;
} ArchTickTimer;
并声明对外获取tick timer的接口:
ArchTickTimer *ArchSysTickTimerGet(VOID)
define LOS_SysTickTimerGet ArchSysTickTimerGet
2.在每个架构下提供默认的tick timer操作:
STATIC ArchTickTimer g_archTickTimer = {
.freq = xxx, 必填
.irqNum = xxx, 必填
.init = xxx, 必填
.getCycle = xxx, 必填
.reload = xxx, 必填
.lock = xxx, 必填
.unlock = xxx, 必填
.tickHandler = NULL, 可选
}
并实现:ArchTickTimer *ArchSysTickTimerGet(VOID) 接口
3.内核los_tick.c中提供对外(其它模块)和公共的tick timer初始化操作函数,
如果用户不想启用系统默认的tick timer,则需要在 "内核初始化之前" 调用接口:
LOS_TickTimerRegister(const ArchTickTimer *timer, const HWI_PROC_FUNC tickHandler)
将用户自己的tick timer或中断处理函数 注册进去。
用户也可以注册自己的中断处理函数(用户不提供,默认使用系统提供的)。
BREAKING CHANGE:
原来版本中每个架构下提供的tick timer相关操作函数为弱函数:
WEAK UINT32 HalTickStart(OS_TICK_HANDLER handler);
WEAK VOID HalSysTickReload(UINT64 nextResponseTime);
WEAK UINT64 HalGetTickCycle(UINT32 *period);
WEAK VOID HalTickLock(VOID);
WEAK VOID HalTickUnlock(VOID);
用户如果需要启用自己的tick timer需要自己实现相关接口(强属性),在 "内核初始化之前" 通过调用:
LOS_TickTimerRegister 接口替换系统默认提供的tick timer相关接口。
无论用户提供的tick timer 还是系统默认提供的,均在内核初始化时启动。
Close #I4N7XV:arch 重构
Signed-off-by: zhushengle <zhushengle@huawei.com>
Change-Id: I83ad0bdf303904f0e73f808b57b60183619fddcd
This commit is contained in:
@@ -30,37 +30,180 @@
|
||||
*/
|
||||
|
||||
#include "los_tick.h"
|
||||
#include "securec.h"
|
||||
#include "los_config.h"
|
||||
#include "los_task.h"
|
||||
#include "los_swtmr.h"
|
||||
#include "los_sched.h"
|
||||
#include "los_debug.h"
|
||||
|
||||
|
||||
LITE_OS_SEC_BSS STATIC ArchTickTimer *g_sysTickTimer = NULL;
|
||||
LITE_OS_SEC_BSS UINT32 g_ticksPerSec;
|
||||
LITE_OS_SEC_BSS UINT32 g_uwCyclePerSec;
|
||||
LITE_OS_SEC_BSS UINT32 g_cyclesPerTick;
|
||||
LITE_OS_SEC_BSS UINT32 g_sysClock;
|
||||
LITE_OS_SEC_BSS BOOL g_sysTimerIsInit = FALSE;
|
||||
|
||||
#if (LOSCFG_BASE_CORE_TICK_HW_TIME == 1)
|
||||
extern VOID platform_tick_handler(VOID);
|
||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||
STATIC UINT64 g_tickTimerBase;
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC VOID OsUpdateSysTimeBase(VOID)
|
||||
{
|
||||
UINT32 period = 0;
|
||||
|
||||
(VOID)g_sysTickTimer->getCycle(&period);
|
||||
g_tickTimerBase += period;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT VOID OsTickTimerBaseReset(UINT64 currTime)
|
||||
{
|
||||
LOS_ASSERT(currTime > g_tickTimerBase);
|
||||
|
||||
g_tickTimerBase = currTime;
|
||||
}
|
||||
#endif
|
||||
|
||||
LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
|
||||
{
|
||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||
OsSchedUpdateSchedTimeBase();
|
||||
#endif
|
||||
|
||||
#if (LOSCFG_BASE_CORE_TICK_HW_TIME == 1)
|
||||
platform_tick_handler();
|
||||
OsUpdateSysTimeBase();
|
||||
#endif
|
||||
|
||||
LOS_SchedTickHandler();
|
||||
}
|
||||
|
||||
UINT64 LOS_SysCycleGet(VOID)
|
||||
LITE_OS_SEC_TEXT VOID OsTickTimerReload(UINT64 responseTime)
|
||||
{
|
||||
return OsGetCurrSysTimeCycle();
|
||||
#if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
|
||||
g_tickTimerBase = LOS_SysCycleGet();
|
||||
#endif
|
||||
g_sysTickTimer->reload(responseTime);
|
||||
}
|
||||
|
||||
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) {
|
||||
/* Turn the timer count */
|
||||
g_tickTimerBase += period;
|
||||
schedTime = g_tickTimerBase + time;
|
||||
}
|
||||
|
||||
LOS_ASSERT(schedTime >= oldSchedTime);
|
||||
|
||||
oldSchedTime = schedTime;
|
||||
LOS_IntRestore(intSave);
|
||||
return schedTime;
|
||||
#endif
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT STATIC UINT32 TickTimerCheck(const ArchTickTimer *tick)
|
||||
{
|
||||
if (tick == NULL) {
|
||||
return LOS_ERRNO_SYS_PTR_NULL;
|
||||
}
|
||||
|
||||
if ((tick->freq == 0) ||
|
||||
(LOSCFG_BASE_CORE_TICK_PER_SECOND == 0) ||
|
||||
(LOSCFG_BASE_CORE_TICK_PER_SECOND > tick->freq)) {
|
||||
return LOS_ERRNO_SYS_CLOCK_INVALID;
|
||||
}
|
||||
|
||||
if (tick->irqNum > (INT32)LOSCFG_PLATFORM_HWI_LIMIT) {
|
||||
return LOS_ERRNO_TICK_CFG_INVALID;
|
||||
}
|
||||
|
||||
if (tick->init == NULL || tick->reload == NULL ||
|
||||
tick->lock == NULL || tick->unlock == NULL ||
|
||||
tick->getCycle == NULL) {
|
||||
return LOS_ERRNO_SYS_HOOK_IS_NULL;
|
||||
}
|
||||
|
||||
if (g_sysTimerIsInit) {
|
||||
return LOS_ERRNO_SYS_TIMER_IS_RUNNING;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT_INIT UINT32 OsTickTimerInit(VOID)
|
||||
{
|
||||
UINT32 ret;
|
||||
HWI_PROC_FUNC tickHandler = (HWI_PROC_FUNC)OsTickHandler;
|
||||
g_sysTickTimer = LOS_SysTickTimerGet();
|
||||
|
||||
ret = TickTimerCheck(g_sysTickTimer);
|
||||
if (ret != LOS_OK) {
|
||||
PRINT_ERR("Tick timer param check failed, Error 0x%x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
g_sysClock = g_sysTickTimer->freq;
|
||||
g_cyclesPerTick = g_sysTickTimer->freq / LOSCFG_BASE_CORE_TICK_PER_SECOND;
|
||||
|
||||
if (g_sysTickTimer->tickHandler != NULL) {
|
||||
tickHandler = g_sysTickTimer->tickHandler;
|
||||
}
|
||||
ret = g_sysTickTimer->init(tickHandler);
|
||||
if (ret == LOS_OK) {
|
||||
g_sysTimerIsInit = TRUE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
LITE_OS_SEC_TEXT UINT32 LOS_TickTimerRegister(const ArchTickTimer *timer, const HWI_PROC_FUNC tickHandler)
|
||||
{
|
||||
UINT32 intSave;
|
||||
UINT32 ret;
|
||||
|
||||
if ((timer == NULL) && (tickHandler == NULL)) {
|
||||
return LOS_ERRNO_SYS_PTR_NULL;
|
||||
}
|
||||
|
||||
if (timer != NULL) {
|
||||
ret = TickTimerCheck(timer);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (g_sysTickTimer == NULL) {
|
||||
g_sysTickTimer = LOS_SysTickTimerGet();
|
||||
}
|
||||
|
||||
if (g_sysTickTimer == timer) {
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_ERRNO_SYS_TIMER_ADDR_FAULT;
|
||||
}
|
||||
|
||||
errno_t errRet = memcpy_s(g_sysTickTimer, sizeof(ArchTickTimer), timer, sizeof(ArchTickTimer));
|
||||
if (errRet != EOK) {
|
||||
PRINT_ERR("%s timer addr fault! errno %d\n", __FUNCTION__, errRet);
|
||||
ret = LOS_ERRNO_SYS_TIMER_ADDR_FAULT;
|
||||
}
|
||||
LOS_IntRestore(intSave);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (g_sysTimerIsInit) {
|
||||
return LOS_ERRNO_SYS_TIMER_IS_RUNNING;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
if (g_sysTickTimer == NULL) {
|
||||
g_sysTickTimer = LOS_SysTickTimerGet();
|
||||
}
|
||||
|
||||
g_sysTickTimer->tickHandler = tickHandler;
|
||||
LOS_IntRestore(intSave);
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -72,7 +215,7 @@ Return : current tick
|
||||
*****************************************************************************/
|
||||
LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID)
|
||||
{
|
||||
return OsGetCurrSchedTimeCycle() / OS_CYCLE_PER_TICK;
|
||||
return LOS_SysCycleGet() / OS_CYCLE_PER_TICK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -176,5 +319,3 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsCpuTick2US(CpuTick *cpuTick, UINT32 *usHi, UINT32
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user