RT-Thread时钟管理

1.时钟节拍

  • 任何操作系统都需要提供一个时钟节拍,这样系统才可以处理和时间有关的事件,如线程的延时,时间片轮转等,时钟节拍可以看作是心跳,时钟节拍停止自增,那么系统就会体止,不在运行
  • 时钟节拍就是一个周期性中断,中断间隔取决于用户的实际应用,一般为1-100ms
  • 时钟节拍率越快,系统的实时响应就越快,但是系统的额外开销就越大
  • 从系统启动开始计数的时钟节拍数称为系统时间
  • RT-Thread中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于1/RT_TICK_PER_SECOND 秒

2.时钟节拍实现方式

  • 时钟节拍由配置为中断触发模式的硬件定时器产生,当中断到来时,将调用一次:void rt_tick_increase(void),通知操作系统已经过去一个系统时钟
  • 不同硬件定时器中断实现都不同,下面的中断函数以stm32定时器为例
    void SysTick_Handler(void)
    {
        /* 进入中断 */
        rt_interrupt_enter();
        ……
        rt_tick_increase();
        /* 退出中断 */
        rt_interrupt_leave();
    }
    在中断函数中调用 rt_tick_increase() 对全局变量 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();
    }
    可以看到全局变量 rt_tick 在每经过一个时钟节拍时,值就会加 1,rt_tick 的值表示了系统从启动开始总共经过的时钟节拍数,即系统时间。此外,每经过一个时钟节拍时,都会检查当前线程的时间片是否用完,以及是否有定时器超时。

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//动态/静态函数


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值