【RT-Thread】学习日记之系统节拍Tick

简介: 【RT-Thread】学习日记之系统节拍Tick

目前在做一个项目使用到了 RT-Thread 操作系统,这里就记录一下在使用过程中的一些学习记录。

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


以 RT-Thread 为例,在创建任务时,需要配置一个时间片:

/**
 * @brief   This function will create a thread object and allocate thread object memory.
 *          and stack.
 * 
 * @param   tick is the time slice if there are same priority thread.
 */
rt_thread_t rt_thread_create(const char *name,
                             void (*entry)(void *parameter),
                             void       *parameter,
                             rt_uint32_t stack_size,
                             rt_uint8_t  priority,
                             rt_uint32_t tick)


线程延时函数的实现,也需要依赖系统节拍:

/**
 * @brief   This function will let current thread delay for some milliseconds.
 *
 * @param   ms is the delay ms time.
 *
 * @return  Return the operation status. If the return value is RT_EOK, the function is successfully executed.
 *          If the return value is any other values, it means this operation failed.
 */
rt_err_t rt_thread_mdelay(rt_int32_t ms)
{
    rt_tick_t tick;

    tick = rt_tick_from_millisecond(ms);

    return rt_thread_sleep(tick);
}
RTM_EXPORT(rt_thread_mdelay);

时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳,中断时间间隔取决于不同的应用,一般是 1ms–100ms,时钟节拍率越快,系统的额外开销就越大,从系统启动开始计数的时钟节拍数称为系统时间。


在 RT-Thread 中,时钟节拍的长度可以根据宏 RT_TICK_PER_SECOND 的定义来调整,该宏定义在头文件 rtconfig.h 中,一个时钟节拍等于 1/RT_TICK_PER_SECOND 秒。默认的 RT_TICK_PER_SECOND 为 100,即一秒会产生 100 个 tick,每个 tick 为 10ms。

/* RT-Thread Kernel */
#define RT_TICK_PER_SECOND 100

时钟节拍由配置为中断触发模式硬件定时器 产生,当中断到来时,将调用一次 rt_tick_increase() 函数,通知操作系统已经过去一个系统时钟,不同的硬件定时器中断实现都不同,下面的中断函数以 STM32 定时器作为示例:

/**
 * This is the timer interrupt service routine.
 */
void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    HAL_IncTick();
    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}


其中 rt_tick_increase() 函数实现对全局变量 rt_tick 的自加,该函数定义在 clock.c 中,程序如下所示:

/**
 * @brief    This function will notify kernel there is one tick passed.
 *           Normally, this function is invoked by clock ISR.
 */
void rt_tick_increase(void)
{
    struct rt_thread *thread;
    rt_base_t level;

    RT_OBJECT_HOOK_CALL(rt_tick_hook, ());

    level = rt_hw_interrupt_disable();

    /* increase the global tick */
#ifdef RT_USING_SMP
    rt_cpu_self()->tick ++;
#else
    ++ rt_tick;
#endif /* RT_USING_SMP */

    /* check time slice */
    thread = rt_thread_self();

    -- thread->remaining_tick;
    if (thread->remaining_tick == 0)
    {
        /* change to initialized tick */
        thread->remaining_tick = thread->init_tick;
        thread->stat |= RT_THREAD_STAT_YIELD;

        rt_hw_interrupt_enable(level);
        rt_schedule();
    }
    else
    {
        rt_hw_interrupt_enable(level);
    }

    /* check timer */
    rt_timer_check();
}

通过 rt_tick_t rt_tick_get(void) 函数可获取当前的系统节拍,可用于记录系统的当前运行时间,该函数定义在 clock.c 中,程序如下所示:

/**
 * @brief    This function will return current tick from operating system startup.
 *
 * @return   Return current tick.
 */
rt_tick_t rt_tick_get(void)
{
    /* return the global tick */
    return rt_tick;
}
RTM_EXPORT(rt_tick_get);

可通过 void rt_tick_set(rt_tick_t tick) 函数设定当前系统的 tick 值,该函数定义在 clock.c 中,程序如下所示:

/**
 * @brief    This function will set current tick.
 *
 * @param    tick is the value that you will set.
 */
void rt_tick_set(rt_tick_t tick)
{
    rt_base_t level;

    level = rt_hw_interrupt_disable();
    rt_tick = tick;
    rt_hw_interrupt_enable(level);
}

clock.c 中还定义了一个 rt_tick_get_millisecond 虚函数,通过该函数可获取当前系统运行的毫秒数,建议在 RT_TICK_PER_SECOND 为 1000 时使用,程序如下:

/**
 * @brief    This function will return the passed millisecond from boot.
 *
 * @note     if the value of RT_TICK_PER_SECOND is lower than 1000 or
 *           is not an integral multiple of 1000, this function will not
 *           provide the correct 1ms-based tick.
 *
 * @return   Return passed millisecond from boot.
 */
RT_WEAK rt_tick_t rt_tick_get_millisecond(void)
{
#if 1000 % RT_TICK_PER_SECOND == 0u
    return rt_tick_get() * (1000u / RT_TICK_PER_SECOND);
#else
    #warning "rt-thread cannot provide a correct 1ms-based tick any longer,\
    please redefine this function in another file by using a high-precision hard-timer."
    return 0;
#endif /* 1000 % RT_TICK_PER_SECOND == 0u */
}

可以使用 rt_tick_get_millisecond 函数通过以下方式计算某个任务的耗时时间:

{
  rt_tick_t start,end;
  start = rt_tick_get_millisecond();
  function_to_get_time();
  end = rt_tick_get_millisecond();
  rt_kprintf("The time consumed is %d ms. \n", end - start);
}

参考来源:RT-Thread


相关文章
|
传感器 数据采集 物联网
STM32:高性能微控制器与广泛的应用领域
STM32:高性能微控制器与广泛的应用领域
835 0
|
3月前
|
前端开发 数据安全/隐私保护
股票持仓截图生成器手机版, 股票持仓图生成器免费,交割单生成器制作工具
代码实现了一个完整的股票持仓截图生成器,包含数据模拟、表格绘制、汇总计算和水印添加功能。
|
1月前
|
安全 测试技术 虚拟化
VMware-三种网络模式原理
本文介绍了虚拟机三种常见网络模式(桥接模式、NAT模式、仅主机模式)的工作原理与适用场景。桥接模式让虚拟机如同独立设备接入局域网;NAT模式共享主机IP,适合大多数WiFi环境;仅主机模式则构建封闭的内部网络,适用于测试环境。内容简明易懂,便于理解不同模式的优缺点与应用场景。
224 0
|
7月前
|
数据采集 消息中间件 API
微店API开发全攻略:解锁电商数据与业务自动化的核心能力
微店开放平台提供覆盖商品、订单、用户、营销、物流五大核心模块的API接口,支持企业快速构建电商中台系统。其API体系具备模块化设计、双重认证机制、高并发支持和数据隔离等特性。文档详细解析了商品管理、订单处理、营销工具等核心接口功能,并提供实战代码示例。同时,介绍了企业级整合方案设计,如订单全链路自动化和商品数据中台架构,以及性能优化与稳定性保障措施。最后,针对高频问题提供了排查指南,帮助开发者高效利用API实现电商数智化转型。适合中高级开发者阅读。
|
11月前
|
传感器 测试技术 芯片
在硬件连接时,如何确定 GPIO 引脚的功能和编号
在硬件连接中,确定GPIO引脚的功能和编号需查阅相关芯片或开发板的官方文档,了解引脚布局图,确认引脚的具体功能和编号,以确保正确连接和编程。
|
小程序 前端开发 Java
200道微信小程序毕业设计最新题目(持续更新,附源码和说明文档)
200道微信小程序毕业设计最新题目(持续更新,附源码和说明文档)
|
存储 调度 容器
RT-Thread快速入门-定时器管理
RT-Thread快速入门-定时器管理
366 0
|
安全 网络安全
用IE浏览器访问网站提示证书错误
当你在Internet Explorer中遇到证书错误提示,通常是因网站SSL/TLS证书问题或浏览器安全设置需调整。解决方法包括: 检查时间设置 调整IE设置 安装证书 调整计算机时间
687 3
|
Ubuntu 编译器 开发工具
如何根据自己的开发板型号下载和配置交叉编译链
【7月更文挑战第9天】为AMD64 Ubuntu配置ARM64开发板交叉编译环境: 1. 下载适配开发板的GCC,如rk3568用Linaro AArch64。 2. 将GCC置于`downloads`等目录。 3. 解压至`/opt/`,如`tar -xvf gcc-linaro-*.tar.xz -C /opt/`。 4. 编辑`~/.bashrc`添加`/opt/gcc-linaro/*/bin`至PATH。 5. 运行`source ~/.bashrc`激活环境变量。 6. 通过`aarch64-linux-gnu-gcc -v`验证安装。
527 0
Clion+STM 32Warn : Failed to open device: LIBUSB_ERROR_NOT_SUPPORTED
Clion+STM 32Warn : Failed to open device: LIBUSB_ERROR_NOT_SUPPORTED
467 0