Liteos源码
以下涉及到的源码为Liteos的develop支线版本。
Liteos的tick是通过systick中断来实现的,软件定时器和所有的延时也是基于tick进行的。
#define OS_SYS_CLOCK (SystemCoreClock)
#define LOSCFG_BASE_CORE_TICK_PER_SECOND (200UL)
OS_SYS_CLOCK为系统时钟频率,设置为40MHz,tick周期设置为200,也就是说每秒systick产生200次中断,每个tick5ms。那么软件定时器和延时函数所能处理的最小时间刻度就是5ms。另外,使用Liteos提供的延时函数LOS_TaskDelay()的参数如果设置为0,那么会立即进行任务切换。
Tickless模式是通过在执行空闲任务的时候使MCU进入睡眠模式实现的。STM32L431的睡眠模式,在数据手册中表述如下:

可以看到有任何的中断或者事件到来都会退出睡眠模式,但是系统的tick是5ms,也就是说每5ms一次的systick中断就必定会唤醒MCU,显然是不符合低功耗的要求的。因此Tickless模式通过在空闲时改变systick的Reload值来改变systick的中断时间,以此来拉长MCU进入睡眠模式的时间。要使用Tickless模式,需要在target_config.h中把LOSCFG_KERNEL_TICKLESS宏设置为YES。
但是SysTick 是一个 24 位的倒计数定时器,当计到 0 时,将从Reload寄存器中自动重装载定时初值。因此延长睡眠时间也不是没有限制的,Reload值最大为0xFFFFFFUL。在睡眠前要先计算需要睡眠的tick数,这个tick数是通过osSleepTicksGet()函数来实现的,是通过取最近一个任务切换即将到达或者最近一个软件定时器定时即将到达的时间来确定,二者取小值(如果没有用软件定时器,那么其值为0xFFFFFFFF,所以就是取最近一个任务切换即将到达的时间)。然后通过睡眠的tick数来设置Reload的值,如果要睡眠的tick数超过最大限制,那么本次要睡眠的tick数就是最大值,也就是在一定时间内必须产生一次systick中断。
使用Tickless模式时关键的几个全局变量定义:
BOOL g_bTicklessFlag = 1; //是否要进入tickless模式,用户
BOOL g_bTickIrqFlag = 0; //是否要进入tickless模式,系统
BOOL g_bReloadSysTickFlag = 0; //是否要重新设置systick的reload值
volatile UINT32 g_uwSleepTicks = 0; //要睡眠的tick数
主要函数:
static inline UINT32 osSleepTicksGet(VOID) //获取要睡眠的tick数
inline VOID osUpdateKernelTickCount(UINT32 uwHwiIndex) //更新内核的TICK数,入参:中断号
VOID osTicklessStart(VOID)
用户通过LOS_TicklessEnable()和LOS_TicklessDisable()函数来设置g_bTicklessFlag的值,以此控制Tickless模式下是否要改变时基。在执行空闲任务的时候会调用osTicklessHandler()函数来进入睡眠模式,接管中断模式下如下:
VOID osTicklessHandler(VOID)
{
if (g_bTickIrqFlag)//tickless模式下如果要改变时基,在systick中断中被赋值
{
g_bTickIrqFlag = 0;

本文介绍了Liteos操作系统中Tickless模式的工作原理和技术细节。通过调整systick中断周期以延长MCU睡眠时间,实现低功耗运行。文章深入解析了关键函数如osTicklessStart()的实现机制,并对比了不同模式下的功耗表现。

2667

被折叠的 条评论
为什么被折叠?



