时钟与定时器

1 时钟管理

1.1时钟节拍

        任何操作系统都需要提供一个时钟节拍,以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。

       RT-Thread 中,时钟节拍长度可以根据 RT_TICK_PER_SECOND 的定义来调整rtconfig.h配置文件中定义:

/* 
 *频率是1000HZ 周期是1/1000 s
 *所以节拍是1ms
 */
#define RT_TICK_PER_SECOND 1000

系统滴答定时器中断处理函数(每1ms触发一次systick定时器中断):

1.2获取系统节拍

/**
 * This function will return current tick from operating system startup
 *
 * @return current tick
 */
rt_tick_t rt_tick_get(void)

1.3定时器 

       定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,定时器有硬件定时器软件定时器之分。

硬件定时器: 芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。

硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。

软件定时器: 由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。

       RT-Thread操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即定时数值必须是OS Tick的整数倍。

1.3.1RT_Thread定时器介绍

       RT-Thread 的定时器提供两类定时器机制:

1、第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。

2、第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止,否则将永远持续执行下去。

       根据定时器超时函数执行时所处的上下文环境,RT-Thread的定时器可以分为HARD_TIMER模式和SOFT_TIMER模式。

HARD_TIMER模式:中断上下文

       定时器超时函数的要求:执行时间应该尽量短,执行时不应导致当前上下文挂起、等待。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存

SOFT_TIMER模式:线程上下文

       该模式被启用后,系统会在初始化时创建一个 timer 线程,然后 SOFT_TIMER 模式的定时器超时函数在都会在timer线程的上下文环境中执行 。    

1.3.2 RT_Thread定时器介绍 

(1) RT-Thread OS启动阶段,执行rtthread_startup函数,在该函数中调用了定时器初始化函数

/* timer system initialization */
rt_system_timer_init();//硬件定时器初始化

/* timer thread initialization */
rt_system_timer_thread_init();//软件定时器初始化

(2)rt_system_timer_init();//硬件定时器初始化

struct rt_list_node
{
    struct rt_list_node *next;     /**< point to next node. */
    struct rt_list_node *prev;     /**< point to prev node. */
};
typedef struct rt_list_node rt_list_t; 

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);
     }
}

/**
 * @brief initialize a list t퍷
 *
 * @param l list to be initialized
 */
rt_inline void rt_list_init(rt_list_t *l)
{
    l->next = l->prev = l;
}

(3)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_SOFT
    int 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
}

 1.3.3定时器工作机制

      下面以一个例子来说明 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_tick=20,从小到大排序链接在 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_tick=30)有一个任务新创建了一个 tick 值为 300 的Timer4定时器,由于Timer4定时器的timeout=rt_tick+300=330,因此它将被插入到Timer2和Timer3定时器中间,形成如下图所示链表结构:

1.3.4、定时器相关接口 

      1、动态创建一个定时器和删除定时器。

/**
 * This function will create a timer
 *
 * @param name the name of timer
 * @param timeout the timeout function
* @param parameter the parameter of timeout function
 * @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 timer's callback function will be called in tick isr. */
* #define RT_TIMER_FLAG_SOFT_TIMER       0x4            /**< soft timer,the timer's callback function will be called in timer thread. */
* @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)
/**
 * This function will delete a timer and release 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)

  2、 初始化和脱离定时器(静态)

/**
 * 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 timeout function
 * @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 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)

3、控制定时器

/**
 * This function will get or set some options of 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 */
* #define RT_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)

1.4、高精度延时

  注意:这个函数只支持低于1个OS Tick的延时, 否则SysTick会出现溢出而不能够获得指定的延时时间。

/**
 * This function will delay for some us.
 *
 * @param us the delay time of us
 */
void rt_hw_us_delay(rt_uint32_t us)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值