学习目标:
学习rt_thread中定时器的相关知识
学习内容:
操作系统中,其核心的节拍时钟仍然是基于硬件时钟的基础上。可以将其称之为节拍。
所谓的软件定时器必须以该节拍为基本单位。
rt_thread的定时器中存在着两种的定时机制,一种是单次的触发定时器,该定时器触发后,只会触发一次的定时器时间。另外一种是周期性的触发定时器事件,那就顾名思义了。
在rt_thread的定时器系统中,维护着两个重要的全局变量:
1.当前系统经过的tick时间的rt_tick(当硬件定时器中断来临时rt_tick+1)
2.定时器链表rt_timer_list.系统新创建并激活的定时器都会按照以超时时间排序的方式插入到rt_timer_list中
所谓的定时器超时函数,就是指定时器的设定时间到了以后,所执行的动作函数称之为超时函数
超时函数存在两种情况:
1.超时函数在系统时钟中断的上下文环境中执行。标识:RT_TIMER_FLAG_HARD_TIMER
在此情形下,对于超时函数的要求与中断服务历程相同,执行时间应该尽可能的短,执行过程中
不应导致当前的上下文挂起,等待。例如在中断的上下文执行过程中,超时函数不应试图去申请动态内存,释放动态
内存等,其中就包括rt_timer_detelet的函数调用。
2.超时函数在线程的上下文环境中执行。标识:RT_TIMER_SOFT_TIMER
在线程上下文使用过程中,没有限制。
定时器管理控制块:
struct rt_timer
{ struct rt_obiect 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_systhem_timer_init(void)
如果要使用SOFT_TIMER,则系统初始化时应该调用下面的函数接口:
void rt-system_timer_thread_init(void);
动态 创建一个定时器时:
rt_timer_t rt_timer_create(const char* name,
void(*timeout)(void* parameter),void* parameter,
rt_tick_t time,rt_uint8_t flag);
定时器创建参数的相关宏定义:
定时器删除函数:
rt_err_t rt_timer_delete (rt_timer_t timer);
调用上述函数,系统会将定时器从rt_timer_list链表中删除,然后释放相应的定时器控制块占有的内存。
初始化一个静态定时器:
void rt_timer_init(rt_timer_t timer,
const char* name,void (*timeout)(void* parameter),void* parameter,
rt_tick_t time,rt_uint8_t flag);
当使用静态创建定时器时,才可以使用脱离定时器函数:
rt_err_t rt_timer_detach(rt_timer_t timer);
该函数仅仅从容器的定时器链表中删除,但是所占有的内存不会被释放。
启动定时器:
rt_err_t rt_timer_start( rt_timer_t timer);
定时器只有被初始化后,并经过定时器启动函数后定时器的状态将改为激活状态(RT_TIMER_FLAG_ACTIVATE)
并按照超时顺序插入到rt_timer_list队列的链表中。
停止定时器
启动定时器后如果想使他停止,可以调用:
rt_err_t rt_timer_stop(rt_timert timer);
调用定时器停止函数后,定时器将改为停止状态,并从rt_timer_list中脱离出来不参与定时器超时检查。
当一个周期定时器超时后,也可以调用这个函数接口停止定时器本身。
控制定时器:
rt_err_t rt_timer_control(rt_timer_t timer,rt_uint8_t cmd,void* arg)