该账号是华为云开发者社区的官方运营账号,提供全面深入的云计算前景分析,丰富的技术干货、程序样本,分享华为云前沿资讯动态。
本文分享自华为云社区“鸿蒙系统轻内核M-Core源码分析系列六次管理”。原作者是zhushy。
本文将继续分析Tick和时间相关的源代码,并向读者介绍鸿蒙系统轻内核的时间管理模块。本文涉及的源代码,以OpenHarmony LiteOS-M内核为例,可以从开源网站https://gitee.com/openharmony/kernel_liteos_m.获得
基于系统时钟,时间管理模块可以分为两部分,一部分是SysTick中断,为任务调度提供必要的时钟节拍;另一部分是向应用程序提供所有与时间相关的服务,例如时间转换和统计功能。
系统时钟由定时器/计数器触发中断产生的输出脉冲产生,一般定义为整数或长整数。输出脉冲的周期称为“时钟节拍”,也称为时标或节拍。滴答是操作系统的基本时间单位,由用户配置的每秒滴答数决定。如果用户配置的每秒滴答数为1000,则一个滴答等于1毫秒的持续时间。另一个时间单位是周期,是系统中最小的时间单位。周期的持续时间由系统主时钟频率决定,即每秒的周期数。对于一个216 MHz的CPU,一秒钟产生216,000,000个周期。

用户以秒和毫秒计算时间,而操作系统以滴答计算时间。当用户需要对系统进行操作时,比如任务暂停和延迟,可以使用时间管理模块进行滴答和秒/毫秒的转换。
接下来,我们来分析一下时间管理模块的源代码。如果涉及开发板,以开发板项目Targets \ Cortex-M7 _ Nucleo _ f 767 zi _ GCC \为例分析源代码。
我们先来看看时间管理模块的配置,然后分析如何初始化和启动。
时间管理模块涉及三个配置项:系统时钟OS_SYS_CLOCK,每秒滴答数los CFG _ BASE _ CORE _ TICK _ per _ second,宏LOSCFG_BASE_CORE_TICK_HW_TIME。LOSCFG_BASE_CORE_TICK_HW_TIME默认关闭。开启时需要提供一个自定义函数VOID platform_Tick_handler(VOID)来执行Tick中断处理函数中的自定义操作。这些配置项在模板开发板项目目录的target_config.h文件中定义,例如targets \ cortex-M7 _ nuclear _ f 767 zi _ gcc \ target _ config . h文件如下:
#define OS_SYS_CLOCK 96000000#define LOSCFG_BASE_CORE_TICK_PER_SECOND (1000UL)#define LOSCFG_BASE_CORE_TICK_HW_TIME 0函数INT32 main(VOID)会调用kernel\src\los_init.c中的函数UINT32 LOS_Start(VOID)来启动系统,系统会调用启动调度函数uint 32 Hal Start schedule(OS _ tick _ handler handler)。源代码如下:
LITE_OS_SEC_TEXT_INIT UINT32 LOS_Start(VOID){ return HalStartSchedule(OsTickHandler);}函数uint 32 haltickstart(OS _ tick _ handler * handler)在kernel \ arch \ arm \ cortex-M7 \ gcc \ los _ context . c中定义,源代码如下。函数参数是Tick中断处理函数OsTickHandler,后面会分析。(1)代码继续调用函数,并进一步调用函数HalTickStart(处理程序)来设置Tick中断开始。⑵将调用汇编函数HalStartToRun开始运行系统,在后续的任务调度系列中将详细分析汇编函数。
LITE_OS_SEC_TEXT_INIT UINT32 HalStartSchedule(OS_TICK_HANDLER handler){ UINT32 ret;⑴ ret = HalTickStart(handler); if (ret != LOS_OK) { return ret; }⑵ HalStartToRun; return LOS_OK; /* never return */}函数HalTickStart(handler)在文件kernel \ arch \ arm \ cortex-M7 \ gcc \ los _ timer . c中定义,源代码如下。我们来分析一下函数的代码实现。(1)检查时间管理模块配置项的合法性。当宏los CFG _ use _ system _ defined _ interrupt打开时,使用系统定义的中断。会在υ处执行代码并调用文件kernel \ arch \ arm \ cortex-M7 \ gcc \ los _ interrupt . c中定义的函数OsSetVector来设置中断向量,这个会在中断系列中详细分析。⑵设置全局变量g_sysClock为系统时钟,G _ cyclepertick为每个tick对应的周期数,g_ullTickCount初始化为0,表示系统tick中断的次数。⑵调用Targets \ Cortex-M7 _ Nucleo _ f 767 zi _ GCC \ Drivers \ CMS is \ Include \ Core _ cm7 . h文件中定义的内嵌函数uint 32 _ tSystick _ config(uint 32 _ t ticks)初始化并启动系统定时器Systick和中断。
WEAK UINT32 HalTickStart(OS_TICK_HANDLER *handler){ UINT32 ret;⑴ if ((OS_SYS_CLOCK == 0) || (LOSCFG_BASE_CORE_TICK_PER_SECOND == 0) || (LOSCFG_BASE_CORE_TICK_PER_SECOND