精品课程网站建设毕业设计论文,wordpress 前端修改,汽车网站建设公司,贝壳找房房源目录
时钟管理
时钟节拍
RTT工程目录结构介绍
配置文件#xff1a;rtconfig.h
获取系统节拍
获取系统节拍数函数
实例
定时器
RT_Thread定时器介绍
定时器源码分析#xff08;了解即可#xff09; rt_system_timer_init (硬件定时器初始化)
rt_system_timer_thr…目录
时钟管理
时钟节拍
RTT工程目录结构介绍
配置文件rtconfig.h
获取系统节拍
获取系统节拍数函数
实例
定时器
RT_Thread定时器介绍
定时器源码分析了解即可 rt_system_timer_init (硬件定时器初始化)
rt_system_timer_thread_init软件定时器初始化
总结
定时器工作机制
定时器相关接口
启动和停止定时器
动态创建定时器
创建定时器
删除定时器
实例
静态创建定时器
初始化定时器
脱离定时器
实例
控制定时器
实例
高精度延时 时钟管理
操作系统需要通过时间来规范其任务本章主要介绍时钟节拍和基于时钟节拍的定时器。
时钟节拍 任何操作系统都需要提供一个时钟节拍以供系统处理所有和时间有关的事件如线程的延时、线程的时间片轮转调度以及定时器超时等。 RT-Thread 中时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整。 rtconfig.h配置文件中定义
/* *频率是1000HZ 周期是1/1000 s*所以节拍是1ms*/
#define RT_TICK_PER_SECOND 1000
RTT工程目录结构介绍 配置文件rtconfig.h
其中包括了内核相关的配置、内部线程通信配置、内存管理、内核设备对象、RTT组件、C特性、设备驱动和USB配置等等
时钟节拍配置属于内核相关配置默认配置为1000表示1000Hz一次节拍为1ms 系统滴答定时器中断处理函数每1ms触发一次systick定时器中断每一次发生中断都会进入中断处理函数
我们可以通过启动文件的中断向量表中进入 void SysTick_Handler(void)
{/* enter interrupt */rt_interrupt_enter();HAL_IncTick();rt_tick_increase();// rt_tick全局变量自加//记录的是系统从启动到现在的时间节拍数/* leave interrupt */rt_interrupt_leave();
}
获取系统节拍
获取系统节拍数函数
/*** This function will return current tick fromoperating system startup** return current tick*/
rt_tick_t rt_tick_get(void)
实例
通过获取系统节拍数来验证时钟节拍1ms一次
... ...
int main(void)
{int i0;rt_tick_t tick0;for(i0;i10;i){tick rt_tick_get();rt_kprintf(tick:%u\n,tick);rt_thread_mdelay(500);}return RT_EOK;
}
运行结果
通过结果可以验证时钟节拍确实为1ms一次 如果我们将频率改为10000Hz即100ms一个节拍 修改会导致程序出现警告division by zero 除数是0 但并不影响运行结果 定时器 定时器是指从指定的时刻开始经过一定的指定时间后触发一个事件,定时器有硬件定时器和软件定时器之分 硬件定时器: 芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟芯片向软件模块提供一组配置寄存器接受控制输入到达设定时间值后芯片中断控制器产生时钟中断。如果用硬件定时器触发中断以后进行的处理中断函数属于中断上下文。硬件定时器的精度一般很高可以达到纳秒级别并且是中断触发方式。 软件定时器: 由操作系统提供的一类系统接口它构建在硬件定时器基础之上使系统能够提供不受数目限制的定时器服务。软件定时器触发的中断回调函数属于线程上下文。 RT-Thread操作系统提供软件实现的定时器以时钟节拍OS Tick的时间长度为单位即定时数值必须是OS Tick的整数倍。
RT_Thread定时器介绍
RT-Thread 的定时器提供两类定时器机制
第一类是单次触发定时器这类定时器在启动后只会触发一次定时器事件然后定时器自动停止。第二类是周期触发定时器这类定时器会周期性的触发定时器事件直到用户手动的停止否则将永远持续执行下去 根据定时器超时函数执行时所处的上下文环境RT-Thread的定时器可以分为HARD_TIMER模式和SOFT_TIMER模式。 HARD_TIMER模式中断上下文 定时器超时函数的要求执行时间应该尽量短减少对正常执行程序的影响执行时不应导致当前上下文挂起、等待。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等 SOFT_TIMER模式线程上下文 该模式被启用后系统会在初始化时创建一个 timer 线程然后 SOFT_TIMER 模式的定时器超时函数在都会在timer线程的上下文环境中执行
定时器源码分析了解即可
1 RT-Thread OS启动阶段执行rtthread_startup函数在该函数中调用了定时器初始化函数
/* timer system initialization */
rt_system_timer_init();/* timer thread initialization */
rt_system_timer_thread_init(); rt_system_timer_init (硬件定时器初始化)
/*** ingroup SystemInit** This function will initialize system timer*/
void rt_system_timer_init(void)
{int i;for (i 0; i sizeof(rt_timer_list) / sizeof(rt_timer_list[0]); i){rt_list_init(rt_timer_list i);}
}
转到rt_list_init()函数定义处可以发现在RTT中内核是通过双向列表的方式来管理定时器的 再转到链表定义处我们可知rt_system_timer_init初始化的是硬件定时器的列表 rt_system_timer_thread_init软件定时器初始化
/*** ingroup SystemInit** This function will initialize system timer thread*/
void rt_system_timer_thread_init(void)
{
#ifdef RT_USING_TIMER_SOFTint i;for (i 0;i sizeof(rt_soft_timer_list) / sizeof(rt_soft_timer_list[0]);i){rt_list_init(rt_soft_timer_list i);}/* start software timer thread */rt_thread_init(timer_thread,timer,rt_thread_timer_entry,RT_NULL,timer_thread_stack[0],sizeof(timer_thread_stack),RT_TIMER_THREAD_PRIO,10);/* startup */rt_thread_startup(timer_thread);
#endif
}
从开始的rt_list_init(rt_soft_timer_list i);中我们可知软件定时器初始化还是先初始化了一个定时器列表不过传参传的是软件定时器的列表
转到定义处 然后初静态创建定时器并启动 启动完成后会执行线程处理函数rt_thread_timer_entry()
在while(1)中做了一个超时检测如果超时则表示软件定时器不存在则将软件定时器线程挂起让CPU调度其它线程。否则执行定时器的正常功能。
/* system timer thread entry */
static void rt_thread_timer_entry(void *parameter)
{rt_tick_t next_timeout;while (1){/* get the next timeout tick */next_timeout rt_timer_list_next_timeout(rt_soft_timer_list);if (next_timeout RT_TICK_MAX){/* no software timer exist, suspend self. */rt_thread_suspend(rt_thread_self());rt_schedule();}else{rt_tick_t current_tick;/* get current tick */current_tick rt_tick_get();if ((next_timeout - current_tick) RT_TICK_MAX / 2){/* get the delta timeout tick */next_timeout next_timeout - current_tick;rt_thread_delay(next_timeout);}}/* check software timer */rt_soft_timer_check();}
}
总结
内核在管理定时器的时候将定时器分为了两类一类是硬件定时器一类是软件定时器分别挂在不同的列表上进行管理。
定时器工作机制 下面以一个例子来说明 RT-Thread 定时器的工作机制。在 RT-Thread 定时器模块中维护着两个重要的全局变量
当前系统经过的 tick 时间 rt_tick当硬件定时器中断来临时它将加 1 定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序的方式插入到rt_timer_list 链表中。 如下图所示系统当前tick值为20在当前系统中已经创建并启动了三个定时器分别是定时时间为50个tick的Timer1、100个tick的Timer2和500个tick的Timer3这三个定时器分别加上系统 当前时间 rt_tick20从小到大排序链接在 rt_timer_list 链表中形成如图所示的定时器链表结构。 而 rt_tick 随着硬件定时器的触发一直在增长每一次硬件定时器中断来临rt_tick 变量会加 1 50个tick以后rt_tick从20增长到70与Timer1的timeout值相等这时会触发与Timer1定时器相关联的超时函数同时将Timer1从rt_timer_list链表上删除。同理100个tick和500个tick过去后与Timer2 和 Timer3 定时器相关联的超时函数会被触发接着将 Time2 和 Timer3 定时器从 rt_timer_list链表中删除。 如果系统当前定时器状态在 10 个 tick 以后rt_tick30有一个任务新创建了一个 tick 值为 300 的Timer4定时器由于Timer4定时器的timeoutrt_tick300330,因此它将被插入到Timer2和Timer3定时器中间形成如下图所示链表结构 定时器相关接口
启动和停止定时器
/*** This function will start the timer** param timer the timer to be started** return the operation status, RT_EOK on OK,-RT_ERROR on error*/rt_err_t rt_timer_start(rt_timer_t timer)
若想使它停止可以使用下面的函数接口
/*** This function will stop the timer** param timer the timer to be stopped** return the operation status, RT_EOK on OK,-RT_ERROR on error*/rt_err_t rt_timer_stop(rt_timer_t timer)
动态创建定时器
动态创建一个定时器和删除定时器
创建定时器
其中参数2指向定时超时的回调函数定时器中断函数来处理当前的超时事件
参数3为传递给超时函数的参数
参数4为定时器时间单位为节拍数
/*** This function will create a timer** param name the name of timer* param timeout the timeout function* param parameter the parameter of timeoutfunction* param time the tick of timer* param flag the flag of timer* #define RT_TIMER_FLAG_ONE_SHOT 0x0 /** one shot timer */
* #define RT_TIMER_FLAG_PERIODIC 0x2 /** periodic timer */
* #define RT_TIMER_FLAG_HARD_TIMER 0x0 /** hard timer,the timers callbackfunction will be called in tick isr. */
* #define RT_TIMER_FLAG_SOFT_TIMER 0x4 /** soft timer,the timers callback function will be called in timerthread. */
* return the created timer object
*/
rt_timer_t rt_timer_create(const char*name,void (*timeout)(void*parameter),void *parameter,rt_tick_t time,rt_uint8_t flag)
其中flag可以传入以下标志
RT_TIMER_FLAG_ONE_SHOT表示单次触发
RT_TIMER_FLAG_PERIODIC表示周期性的触发 返回值为一个结构体指针 结构体描述当前定时器的信息 删除定时器
传入参数为定时器的结构体指针返回值为错误码正确为RT_EOK错误为负的RT_ERROR
/*** This function will delete a timer andrelease timer memory** param timer the timer to be deleted** return the operation status, RT_EOK on OK;-RT_ERROR on error*/
rt_err_t rt_timer_delete(rt_timer_t timer)
实例
首先对动态创建定时器函数进行参数配置其中标志使用了周期性触发和使用软件定时器。然后定义中断函数创建一个定时器结构体指针来接收返回值如果创建失败就返回-没有内存 运行效果
其中timer里面显示了四个定时器包括了自己创建的tm_demo处于deactivated未活动的状态其它三个定时器为系统创建的tshell、tidle0和timer 完善超时处理函数的内容3s打印一次数据启动定时器
运行效果
可以发现定时器状态已经开启 静态创建定时器
初始化定时器
/*** This function will initialize a timer,normally this function is used to* initialize a static timer object.** param timer the static timer object (typedef struct rt_timer *rt_timer_t;)* param name the name of timer* param timeout the timeout function* param parameter the parameter of timeoutfunction* param time the tick of timer* param flag the flag of timer*/
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)
脱离定时器
静态定时器不需要再使用时可以使用下面的函数接口脱离定时器:
/*** This function will detach a timer from timermanagement.** param timer the static timer object** return the operation status, RT_EOK on OK;RT_ERROR on error*/
rt_err_t rt_timer_detach(rt_timer_ttimer)
实例 运行结果 当前时间节拍数 控制定时器
/*** This function will get or set some optionsof the timer** param timer the timer to be get or set* param cmd the control command* param arg the argument* #define RT_TIMER_CTRL_SET_TIME 0x0 /** set timer control command*/* #define RT_TIMER_CTRL_GET_TIME 0x1 /** get timer control command*/* #define RT_TIMER_CTRL_SET_ONESHOT 0x2 /** change timer to one shot */
* #defineRT_TIMER_CTRL_SET_PERIODIC 0x3 /** change timer to periodic*/
* return RT_EOK
*/
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
实例
以重新设置定时器时间为例15s中后修改定时节拍数为1000 高精度延时
注意这个函数只支持低于1个OS Tick系统节拍的延时 否则SysTick会出现溢出而不能够获得指定的延时时间
一般用于IIC、SPI等总线通信
/*** This function will delay for some us.** param us the delay time of us*/
void rt_hw_us_delay(rt_uint32_t us)