1.时钟节拍
- 任何操作系统都需要提供一个时钟节拍,这样系统才可以处理和时间有关的事件,如线程的延时,时间片轮转等,时钟节拍可以看作是心跳,时钟节拍停止自增,那么系统就会体止,不在运行
- 时钟节拍就是一个周期性中断,中断间隔取决于用户的实际应用,一般为1-100ms
- 时钟节拍率越快,系统的实时响应就越快,但是系统的额外开销就越大
- 从系统启动开始计数的时钟节拍数称为系统时间
- RT-Thread中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于1/RT_TICK_PER_SECOND 秒
2.时钟节拍实现方式
- 时钟节拍由配置为中断触发模式的硬件定时器产生,当中断到来时,将调用一次:void rt_tick_increase(void),通知操作系统已经过去一个系统时钟
- 不同硬件定时器中断实现都不同,下面的中断函数以stm32定时器为例
在中断函数中调用 rt_tick_increase() 对全局变量 rt_tick 进行自加void SysTick_Handler(void) { /* 进入中断 */ rt_interrupt_enter(); …… rt_tick_increase(); /* 退出中断 */ rt_interrupt_leave(); }
可以看到全局变量 rt_tick 在每经过一个时钟节拍时,值就会加 1,rt_tick 的值表示了系统从启动开始总共经过的时钟节拍数,即系统时间。此外,每经过一个时钟节拍时,都会检查当前线程的时间片是否用完,以及是否有定时器超时。void rt_tick_increase(void) { struct rt_thread *thread; /* 全局变量 rt_tick 自加 */ ++ rt_tick; /* 检查时间片 */ thread = rt_thread_self(); -- thread->remaining_tick; if (thread->remaining_tick == 0) { /* 重新赋初值 */ thread->remaining_tick = thread->init_tick; /* 线程挂起 */ rt_thread_yield(); } /* 检查定时器 */ rt_timer_check(); }
3.获取时钟节拍
在程序中,用户可以通过rt_tick_get 来获取系统时间,示例代码如下:
static void thread1_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1)
{
/* 线程 1 采用低优先级运行,一直打印计数值 */
rt_kprintf("system tick : %d\n", rt_tick_get());
rt_thread_mdelay(500);
}
}
每过500毫秒就会获取一次系统时间tick,同时输出到串口助手中
可以看出每过500ms输出一次系统时间,误差在2ms左右
4.RT-Thread定时器
- 定时器是指在经过一定时间后触发特定事件
- RT-Thread有两种定时器模式:
硬件定时器(HARD_TIMER)和软件定时器(SOFT_TIMER) - 硬件定时器:是芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。
软件定时器:是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务,软件定时定时时间只能以时间节拍为定位,如果OS_tick为10ms那么软件定时器的时间间隔必须为20ms,30ms不能为5ms,15ms - HARD_TIMER模式的定时器函数是在中断上下文函数中执行的,可以看作是触发了中断,此模式下的定时回调函数和中回调函数的要求相同:执行时间应该尽量短,执行时不应导致当前上下文挂起、等待。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。
使用HARD_TIMER模式可以在初始化/创建定时器时使用参数RT_TIMER_FLAG_HARD_TIMER 来指定 - SOFT_TIMER模式:通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。
该模式被启用后,系统会在初始化时创建一个 timer 线程,然后 SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行。
可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。 - 定时器和线程一样,也定义了控制块:
struct rt_timer { struct rt_object parent; rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL]; /* 定时器链表节点 */ void (*timeout_func)(void *parameter); /* 定时器超时调用的函数 */ void *parameter; /* 超时函数的参数 */ rt_tick_t init_tick; /* 定时器初始超时节拍数 */ rt_tick_t timeout_tick; /* 定时器实际超时时的节拍数 */ }; typedef struct rt_timer *rt_timer_t;
- 定时器相关函数:
void rt_system_timer_init(void);//系统启动时初始化硬件定时器管理系统
void rt_system_timer_thread_init(void);//系统启动时初始化软件定时器管理系统
rt_timer_create(const char* name, void (*timeout)(void* parameter), void* parameter, rt_tick_t time, rt_uint8_t flag);//定时器创建函数,类似于线程创建
rt_timer_start//定时器启动函数函数,调用后函数开始计时
rt_tiemr_stop/control//定时器停止控制函数
rt_timer_delete/detach//动态/静态函数