【LiteOS】小白进阶之 LiteOS 时间管理解析
华为 LiteOS 的时间管理模块通过系统时钟提供应用程序所需的时间服务功能。系统时钟由定时/计数器产生输出脉冲触发中断而生成,其周期称为“时钟滴答”,可静态配置为秒或毫秒级计时单位。用户通常以秒为单位进行操作(如任务挂起),而芯片 CPU 则基于“时钟滴答”进行计数。模块支持将秒制转换为“时钟滴答”计数(tick),并通过“滴答定时器”实现系统任务调度的中断查询功能。此外,该模块还提供时间统计功能(获取每秒 tick 数)以及延迟处理功能(延迟指定 tick 数)。开发过程中需注意以下几点:1)在使能中断后才能获取系统 tick 数;2)系统的 tick 数不作为准确的时间计算依据;3)需预先配置 OSSYSCLOCK 和 LOSCFGBASECORETICKPER_SECOND 两个选项以完成相关操作。
1、基本概念
时间管理依托系统时钟作为基础,并为应用程序提供全部与时间相关的各种服务。
系统时钟的产生机制是通过定时器/计数模块生成的输出脉冲来触发中断事件的过程;其通常采用的定义形式是基于整数或长整数。
输出脉冲的周期叫做一个“时钟滴答”。
系统时钟也称为时标或者 Tick,一个 Tick 的时长可以静态配置。
由于系统操作通常涉及时间同步需求,在实际应用中若用户采用秒或毫秒作为定时基准,则需要系统进行相应的转换处理。具体而言,在任务挂起、延时等操作中输入的时间值会被统一转换为Chip CPU的时间基准单位(即Tick),以保证系统操作的一致性和正确性。
Tick 与秒之间的对应关系可以配置。
华为 LiteOS 的时间管理模块通过支持时间转换、统计和延迟控制来应对用户对时间相关需求的各种情况提出解决方案。
2、相关概念
Cycle:
系统最小的计时单位。
Cycle 的时长由系统主频决定,系统主频就是每秒钟的 Cycle 数。
Tick:
Tick 是操作系统的一个核心组件,在特定系统架构下表示为一个固定的时间间隔。其具体数值取决于系统的主频以及每秒的Tick次数,并通过配置文件指定。
功能:
Huawei LiteOS系统中的时间管理主要提供以下两种功能:
时间转换:根据主频实现CPU Tick数到毫秒、微秒的转换。
时间统计:获取系统Tick数。
3、滴答定时器
为了完成系统任务调度的目标, 系统设计中必要引入一个定时中断机制用于持续监控和检查系统中的各条链表中处于完成状态的任务序列
在 Cotex 核中有一个 Systick 定时器,可以用来做系统节拍定时器。
由主函数[...]中,程序将执行调用。
LOS_EnableTick();
用于完成定时器的初始化,在文件中有一个全局变量需要根据处理器进行修改。
static 无符号整型 system_clock_frequency 定义为 eight million eight hundred thousand;
可以看出系统定义的是 1ms 中断
定时中断函数是 void SysTick_Handler(void)
将数据加载至 LITE_OS_SEC_VEC 的 HWI_PROC_FUNC 指针及其相关属性 m_pstHwiForm[OS_M4_VECTOR_CNT] 中
4、时间管理的典型开发流程
确认 los_config.h 中配置项 LOSCFG_BASE_CORE_TICK_HW_TIME 为 YES 开启状态。
在 los_config.h 中配置每秒的 Tick 数 LOSCFG_BASE_CORE_TICK_PER_SECOND;
调用时间转换接口后,在完成计数值统计的基础上,
通过LOSTickCountGet函数访问全局g ullTickCount变量。
注意事项:
必须在系统时钟使能之后获取系统 Tick 数。时间主要依靠los_config.h中的OS_SYS_CLOCK和LOSCFG_BASE_CORE_TICK_PER_SECOND这两个配置参数来完成功能。
当系统处于关断状态时,在发生中断时会跳过对 tick 数的计数。因此,在这种情况下,系统无法基于 tick 数准确计算时间。
5、示例
时间转换:
将毫秒数转换为 Tick 数,或将 Tick 数转换为毫秒数。
时间统计和时间延迟:
统计每秒的 Cycle 数、Tick 数和延迟后的 Tick 数。
配好 LOSCFG_BASE_CORE_TICK_PER_SECOND 每秒的 Tick 数。
配好 OS_SYS_CLOCK 系统时钟,单位: Hz。
时间转换:
VOID Example_TransformTime(VOID)
{
UINT32 uwMs;
UINT32 uwTick;
uwTick = LOS_MS2Tick(10000); // 10000 ms 数转换为 Tick 数
printf("uwTick = %d \n",uwTick);
uwMs= LOS_Tick2MS(100); // 100 Tick 数转换为 ms 数
printf("uwMs = %d \n",uwMs);
}
时间统计和时间延迟:
UINT32 Example_GetTick(VOID)
{
UINT32 uwRet = LOS_OK;
UINT32 uwcyclePerTick;
UINT64 uwTickCount1,uwTickCount2;
uwcyclePerTick = LOS_CyclePerTickGet(); // 每个 Tick 多少 Cycle 数
if(0 != uwcyclePerTick)
{
dprintf("LOS_CyclePerTickGet = %d \n", uwcyclePerTick);
}
uwTickCount1 = LOS_TickCountGet(); // 获取 Tick 数
if(0 != uwTickCount1)
{
dprintf("LOS_TickCountGet = %d \n", (UINT32)uwTickCount1);
}
LOS_TaskDelay(200);//延迟200 Tick
uwTickCount2 = LOS_TickCountGet();
if(0 != uwTickCount2)
{
dprintf("LOS_TickCountGet after delay = %d \n", (UINT32)uwTickCount2);
}
if((uwTickCount2 - uwTickCount1) >= 200)
{
uwRet = LOS_InspectStatusSetByID(LOS_INSPECT_SYSTIC,LOS_INSPECT_STU_SUCCESS);
if (LOS_OK != uwRet)
{
dprintf("Set Inspect Status Err\n");
}
return LOS_OK;
}
else
{
uwRet = LOS_InspectStatusSetByID(LOS_INSPECT_SYSTIC,LOS_INSPECT_STU_ERROR);
if (LOS_OK != uwRet)
{
dprintf("Set Inspect Status Err\n");
}
return LOS_NOK;
}
}
refer:
<>
