前言
时钟是所有系统工作的心脏,单片机有自己的主频,每一步逻辑算术运算都发生在时钟信号的翻转时刻;RTOS自然也有自己的时钟系统,本文着眼于RTT的系统时钟以及定时器两个方向对RTT的内核进行阐述
系统时钟
RTOS的时钟是线程运行的最小时间片,也是系统调度发生的最小单位,接下来我们依次来看OS tick从哪来,怎么起作用
系统时钟的源头
在rtt_port.c内,MCU厂商会在此通过自己的硬件时钟(mchtimer)设置一个周期性的中断,在这个硬件中断中,调用 rt_tick_increase()接口,实现tick的自增
需要注意的是,RT_TICK_PER_SECOND是定义在rtconfig.h中的一个常量,因此,在这个硬件中断中,你需要根据自身MCU的主频来设置相应的中断触发间隔。
时钟增长做了什么
在硬件时钟的中断中,除了将下一次中断触发的时间设置成一个预期的时间点,其他只调用了rt_tick_increase();我们看一下他做了什么
void rt_tick_increase(void)
{
struct rt_thread *thread;
rt_base_t level;
RT_OBJECT_HOOK_CALL(rt_tick_hook, ());
level = rt_hw_interrupt_disable();
/* increase the global tick */
#ifdef RT_USING_SMP
rt_cpu_self()->tick ++;
#else
++ rt_tick;
#endif /* RT_USING_SMP */
/* check time slice */
thread = rt_thread_self();
-- thread->remaining_tick;
if (thread->remaining_tick == 0)
{
/* change to initialized tick */
thread->remaining_tick = thread->init_tick;
thread->stat |= RT_THREAD_STAT_YIELD;
rt_hw_interrupt_enable(level);
rt_schedule();
}
else
{
rt_hw_interrupt_enable(level);
}
/* check timer */
rt_timer_check();
}
概括来说,当OS tick增长时,会依次进行以下操作:
1.如果你注册了tick hook,那么会自动执行
2.禁用全局中断
3.全局变量rt_tick自增
4.获取当前运行线程的句柄,将其剩余时间减少一个tick
5.如果当前运行线程剩余时间为0,则打开全局中断,进行一次线程调度
6.打开全局中断
7.检查是否有定时器超时
关于线程调度的详细内容,会展其他文章内进行展开,接下来着重讲一下第7点,与定时器有关的内容
定时器
定时器结构体
首先我们来看下timer struct的源码,结构体的成员就是创建时需要传入的参数
struct rt_timer
{
struct rt_object parent; /**< inherit from rt_object */
rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL];
void (*timeout_func)(void *parameter); /**< timeout function */
void *parameter; /**< timeout function's parameter */
rt_tick_t init_tick; /**< timer timeout tick */
rt_tick_t timeout_tick; /**< timeout tick */
};
typedef struct rt_timer *rt_timer_t;
首先的第一个成员是rt_object parent,该成员就是本系列第一篇文章中提到的内核成员的公共部分,在此不再展开
其次需要传入超时回调函数,回调函数所需的参数以及超时时间
这里展开一下row[RT_TIMER_SKIP_LIST_LEVEL];

最低0.47元/天 解锁文章
994

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



