RT-Thread 时钟 timer delay 相关

前言

  • 此处,介绍对delay 时钟 timer 这几部分之间的关联和相关的知识点;
  • 本来只是想介绍一下 delay的,但是发现说到delay 不先 提到 先验知识 晶振\时钟\时钟节拍\定时器 好像没法解释透彻,所以就变成了 晶振\时钟\时钟节拍\定时器\delay 的很简单的概括一遍;
  • 并附带上能直接运行的示例代码;

一个可以跳过的Tip -> 为了大家方便跳过,我设置成了图片,赶时间可以不点开

在这里插入图片描述


晶振 \ 时钟 \ 时钟节拍 \ 定时器 \ delay

定义

  • 晶振(Crystal Oscillator):
    晶振是硬件级别的时钟源,为微控制器(MCU)提供基准频率。它是系统所有时间相关功能的根基。晶振的频率决定了MCU的主时钟频率,通常称为HCLK(主时钟)。这个频率是非常重要的,因为它直接影响到微控制器的执行速度和整个系统的性能。
  • 时钟(Clock):
    在 RT-Thread 中,时钟通常指的是系统时钟,它是由晶振通过分频、倍频等方式产生的。系统时钟为操作系统和应用程序提供时间基准。系统时钟可以分为不同的类别,如核心时钟、外设时钟等,它们由晶振经过不同的处理得到。
  • 时钟节拍(Tick):
    时钟节拍是操作系统的基本时间单位,RT-Thread 通过硬件定时器来产生固定频率的时钟节拍。每一个时钟节拍代表操作系统中一个最小的时间片段。操作系统利用这些时钟节拍来进行任务调度、延时处理等操作。时钟节拍的频率(通常称为Tick Rate)决定了系统调度的精度和响应速度。例如,一个Tick Rate为1000Hz的系统每个时钟节拍代表1ms。
  • 定时器(Timer):
    定时器是基于时钟节拍工作的,用于执行定时任务。在 RT-Thread 中,定时器可以是一次性的或周期性的。定时器使用时钟节拍来计算时间,当达到指定的时钟节拍数时,定时器超时并执行相应的回调函数。
  • delay:
    delay 函数(在 RT-Thread 中通常为 rt_thread_delay())用于暂停当前线程执行指定的时间段。这个延时是以时钟节拍为单位的。当线程调用 rt_thread_delay() 时,它会被挂起,直到指定的时钟节拍数过去。在这段时间内,调度器会将CPU控制权转移给其他就绪状态的线程。

前面的解释可能太长了,我们再精简一点


  • 晶振(Crystal Oscillator):
    晶振提供了硬件级别的时钟源,它确定了微控制器(MCU)的主时钟频率(HCLK),这直接影响微控制器的执行速度和整个系统的性能。晶振是所有时间管理和计时功能的基础。
  • 时钟(Clock):
    系统时钟是由晶振产生的,可以通过分频、倍频等方式调整,为操作系统和应用程序提供时间基准。时钟可以有不同的类型(如核心时钟、外设时钟),它们支持系统各个部分的运作和时间管理。
  • 时钟节拍(Tick):
    时钟节拍是由系统时钟驱动的,表示操作系统的基本时间单位,用于任务调度和时间管理。时钟节拍的频率(Tick Rate)决定了系统的调度精度和响应速度,每个时钟节拍代表了系统中的一个固定时间片。
  • 定时器(Timer):
    定时器利用时钟节拍来计划和执行定时任务。它可以设置为一次性或周期性,用于在特定的时间点或经过特定时间段后执行任务。定时器的工作是基于时钟节拍的,它们使得在精确的时间执行任务成为可能。
  • delay:
    rt_thread_delay() 函数用于使当前线程暂停执行特定的时钟节拍数,从而提供延时功能。如果调用官方api,在此期间,CPU的控制权会转移给其他就绪状态的线程,实现有效的多任务处理。

一句话概括


  • 晶振为系统提供基本的时间频率,系统时钟根据晶振调整形成不同的时间基准
  • 时钟节拍根据系统时钟生成,为操作系统提供一个均匀的时间度量
  • 定时器和延时功能(delay)则是基于这些时钟节拍来安排和管理时间和任务的执行。
  • 观察 \ 运行 \ 修改 下方代码,获得更深入了解

示例代码

  • 通过这个示例,可以展示 RT-Thread 如何处理线程延时和定时器回调,以及如何利用系统的时钟节拍来进行时间管理和任务调度。
  • 在这个示例中,我们首先创建了一个线程 my_thread,它在一个循环中每隔一秒打印一次计数器 count 的值,并通过 rt_thread_delay() 函数实现延时。RT_TICK_PER_SECOND 定义了一秒内的时钟节拍数,因此 rt_thread_delay(RT_TICK_PER_SECOND) 将使线程延时一秒。
  • 接下来,我们创建了一个周期性定时器 my_timer,它每秒触发一次,并在每次触发时打印出 “Timer tick”。定时器使用 RT_TICK_PER_SECOND 作为超时时间,设置为周期性定时器 RT_TIMER_FLAG_PERIODIC,这意味着它会每隔一秒自动重启并触发回调函数 timer_callback。
#include <rtthread.h>

#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5

/* 定义线程控制块 */
static struct rt_thread my_thread;
/* 定义线程栈 */
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t my_thread_stack[THREAD_STACK_SIZE];

/* 线程入口函数 */
static void my_thread_entry(void *parameter)
{
    rt_uint32_t count = 0;

    /* 线程主循环 */
    while (1)
    {
        /* 打印信息并延时一秒 */
        rt_kprintf("Thread count: %d\n", count++);
        rt_thread_delay(RT_TICK_PER_SECOND); // 延时1秒,RT_TICK_PER_SECOND是系统时钟节拍数,代表一秒
    }
}

/* 定时器回调函数 */
static void timer_callback(void *parameter)
{
    rt_kprintf("Timer tick\n");
}

/* 应用程序入口 */
int main(void)
{
    rt_timer_t my_timer;
    rt_err_t result;

    /* 初始化线程 */
    result = rt_thread_init(&my_thread,
                            "mythread",
                            my_thread_entry,
                            RT_NULL,
                            &my_thread_stack[0],
                            sizeof(my_thread_stack),
                            THREAD_PRIORITY,
                            THREAD_TIMESLICE);
    if (result == RT_EOK)
    {
        rt_thread_startup(&my_thread);
    }

    /* 创建定时器 */
    my_timer = rt_timer_create("mytimer",          // 定时器名称
                               timer_callback,     // 定时器到期时回调的函数
                               RT_NULL,            // 调用回调函数时传递的参数
                               RT_TICK_PER_SECOND, // 定时时间,这里设置为1秒
                               RT_TIMER_FLAG_PERIODIC); // 定时器模式,周期性执行

    /* 启动定时器 */
    if (my_timer != RT_NULL)
    {
        rt_timer_start(my_timer);
    }

    return 0;
}


  • 写到这里了,其实对 delay 定时器 基本的了解已经搭建起来了,其实对于开发而言,差不多够用了
  • 感兴趣的话,可以继续往下翻,我们看一下更深入的准确的定义

在这里插入图片描述


定义

  • delay 和 sleep 是两种差不多的操作在不同平台上的叫法
  • 一般不需要太过关注如何区分,在这里我们看作是一样的
  • delay 我们这里提到两种实现方式,一种是通过估计计算耗时来实现延时;另一种是 Timer定时器实现;通过估计计算耗时的方式我们没什么好说的,我们关注的是 相对智能的\高效的 基于 时钟(timer)实现的
  • 在介绍之前,我们需要一起提到 晶振\时钟\时钟节拍\定时器\delay 之间的关系
  • 在 RT-Thread 实时操作系统中,delay 函数(如 rt_thread_delay())用于挂起当前线程一定的时间。在这段时间内,CPU 将不会执行当前线程,而是转而执行其他的就绪状态线程。如果没有其他线程处于就绪状态,则可能执行空闲线程(idle thread),该线程通常用于执行低优先级的后台任务,如内存清理和系统监视。

  • RT-Thread 的 rt_thread_delay() 函数是专门设计用于多任务环境的,不同于 MicroPython 的 time.sleep(),RT-Thread 的延时操作是为多线程设计的,确实会将 CPU 时间让给其他的线程。这是因为 RT-Thread 是一个完整的实时操作系统,支持多线程和任务调度,所以它可以在一个线程暂停执行时调度其他线程运行。

  • 在 RT-Thread 中,当你调用 rt_thread_delay() 时,你实际上是将当前线程放入睡眠状态直到指定的延时时间过去。这个功能使得 CPU 资源可以被有效地分配给其他需要执行的线程,从而提高系统的总体效率和响应性。

  • 总结来说,RT-Thread 中的 delay 类操作(如 rt_thread_delay())确实会导致当前线程挂起,并允许其他线程使用 CPU。这与 MicroPython 中的 time.sleep() 在操作系统层面上有相似的效果,尽管底层的实现机制和支持的功能可能不同,因为 RT-Thread 是一个多线程的实时操作系统,而 MicroPython 通常运行在单线程环境中。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力回答你的问题。首先,RT-Thread是一个实时操作系统,它提供了一些基本的实时操作系统功能,例如线程、信号量、消息队列、定时器等。其中,定时器是一种非常重要的实时操作系统功能,它可以用来在指定的时间间隔内执行一些操作。 在RT-Thread中,定时器的实现是基于软件定时器,即在内核中维护一个定时器列表,每个定时器都有一个超时时间。当定时器到期时,内核会调用定时器回调函数来执行相应的操作。 下面是RT-Thread定时器的源码分析: 1. 定时器结构体 在RT-Thread中,定时器的结构体定义如下: ```c struct rt_timer { char name[RT_NAME_MAX]; /* 定时器名称 */ rt_list_t list; /* 定时器列表 */ rt_tick_t timeout_tick; /* 定时器超时时间 */ rt_tick_t init_tick; /* 定时器初始时间 */ rt_uint8_t flag; /* 定时器标志 */ rt_uint8_t state; /* 定时器状态 */ void (*timeout_func)(void* parameter); /* 定时器回调函数 */ void* parameter; /* 回调函数参数 */ }; ``` 可以看到,定时器结构体包含了定时器的名称、超时时间、标志、状态、回调函数等信息。 2. 定时器创建 在RT-Thread中,定时器的创建函数是rt_timer_create(),它的函数原型如下: ```c rt_err_t rt_timer_create(rt_timer_t *timer, const char *name, void (*timeout_func)(void* parameter), void* parameter, rt_tick_t time, rt_uint8_t flag); ``` 其中,timer表示定时器指针,name表示定时器名称,timeout_func表示定时器回调函数,parameter表示回调函数参数,time表示定时器超时时间,flag表示定时器标志。 rt_timer_create()函数会在内核中创建一个定时器,并将定时器添加到定时器列表中。如果创建成功,函数返回RT_EOK,否则返回错误码。 3. 定时器启动 在RT-Thread中,定时器的启动函数是rt_timer_start(),它的函数原型如下: ```c rt_err_t rt_timer_start(rt_timer_t timer); ``` rt_timer_start()函数会启动指定的定时器,并将其状态设置为RT_TIMER_FLAG_ACTIVATED。如果启动成功,函数返回RT_EOK,否则返回错误码。 4. 定时器停止 在RT-Thread中,定时器的停止函数是rt_timer_stop(),它的函数原型如下: ```c rt_err_t rt_timer_stop(rt_timer_t timer); ``` rt_timer_stop()函数会停止指定的定时器,并将其状态设置为RT_TIMER_FLAG_DEACTIVATED。如果停止成功,函数返回RT_EOK,否则返回错误码。 5. 定时器删除 在RT-Thread中,定时器的删除函数是rt_timer_delete(),它的函数原型如下: ```c rt_err_t rt_timer_delete(rt_timer_t timer); ``` rt_timer_delete()函数会删除指定的定时器,并释放相应的资源。如果删除成功,函数返回RT_EOK,否则返回错误码。 以上就是RT-Thread定时器的源码分析,希望能对你有所帮助。如果你有其他问题,可以继续问我。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值