一、系统时钟

rt-thread的系统时钟模块采用全局变量rt_tick作为系统时钟节拍,该变量在系统时钟中断函数中不断加1。而系统时钟中断源和中断间隔一般由MCU硬件定时器(如stm32的嘀嗒定时器)决定,rt_tick初始值为0,每次MCU产生硬件定时中断后,在中断函数中不断加1,即rt_tick变量值与MCU硬件定时器定时中断间隔的乘积为系统真正运行时间(例如rt_tick=10,stm32嘀嗒定时器每隔1ms产生中断,则系统上电运行时间为10ms)。

在bsp/stm32f40x/drivers/board.c中设置MCU硬件定时器定时间隔,以及执行相应定时器中断函数:

void  SysTick_Configuration(void)
{
RCC_ClocksTypeDef rcc_clocks;
rt_uint32_t cnts; RCC_GetClocksFreq(&rcc_clocks);//获得系统的晶振频率

//RT_TICK_PER_SECOND在rtconfig.h中配置,表示每秒包含的系统时钟节拍数。默认配置为100,则嘀嗒定时器中断间隔为10ms,rt_tick每隔10ms加1,即默认情况下1s内包含100个系统时钟节拍,每个时钟节拍tick表示10ms。为了提高 精度,一般修改宏定义为1000,即1s内包含1000个系统时钟节拍(此时嘀嗒定时器中断间隔为1ms,每个时钟节拍tick则表示1ms)。
cnts = (rt_uint32_t)rcc_clocks.HCLK_Frequency / RT_TICK_PER_SECOND;
cnts = cnts / ;
    SysTick_Config(cnts);                                //配置系统tick,函数在core_cm4.h中实现,使能嘀嗒定时器中断、定时器时钟源频率HCLK=168MHZ、启动嘀嗒定时器
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//配置定时器时钟源,函数在misc.c中实现,将定时器时源钟频率设置为HCLK/8=21MHZ
} void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();//表示进入中断,在src/irp.c中定义,中断嵌套计数器rt_interrupt_nest加1 rt_tick_increase(); //rt_tick加1,并检查当前运行线程的剩余时间片是否耗尽,若耗尽则让出处理器并重新调度线程,接着执行硬件定时器中断模式下的定时器超时检查rt_timer_check(); /* leave interrupt */
rt_interrupt_leave();//表示进入中断,在src/irp.c中定义,中断嵌套计数器rt_interrupt_nest减1
}

二、硬件定时器中断模式下线程调度驱动

在src/clock.c中:

void rt_tick_increase(void)
{
struct rt_thread *thread; /* increase the global tick */
++ rt_tick; //全局变量系统时钟节拍数加1 /* check time slice */
thread = rt_thread_self(); //获取当前运行的线程 -- thread->remaining_tick; //当前运行线程的剩余时间片减1
if (thread->remaining_tick == )//如果当前运行线程无剩余时间
{
/* change to initialized tick */
thread->remaining_tick = thread->init_tick;//重新将线程的剩余时间片设置为初始化时间片 /* yield */
rt_thread_yield();//将此线程从调度器就绪队列中取出来放到同优先级线程链表末尾,然后再次调度
} /* check timer */
rt_timer_check();//检查定时器链表上是否有时间到达的时钟,即包括自定义的定时器,也包括线程睡眠时启动的线程定时器
}

由上述代码可见,一旦系统产生时钟中断,在嘀嗒定时器中断函数中,系统首先将检查当前正在运行的线程剩余时间片是否耗尽,如果耗尽则将其从调度器就绪队列中取出放到同优先级线程链表末尾,然后再重新调度线程;接着检查是否有休眠的线程时间到达(即线程睡眠时启动的线程定时器是否超时),如果有则触发相应的线程定时器超时函数rt_thread_timeout(将当前挂起的线程加入到调度器就绪队列后重新调度),从而将线程从睡眠中唤醒。

总而言之,在硬件定时器中断模式下,系统时钟中断(MCU硬件定时器中断或嘀嗒定时器中断)是rt-thread线程调度的驱动力。

三、软件定时器线程模式下线程调度驱动

若在rtconfig.h中定义了宏RT_USING_TIMER_SOFT,则使用软件定时器线程模式,此模式下系统中存在定时器线程timer_thread(在rt_system_timer_thread_init中初始化)。在此线程入口函数中通过rt_tick的增加不停地检查定时器链表中是否有定时器超时,其中也包含线程睡眠时启动的线程定时器,一旦线程对应的定时器超时,则触发相应的线程定时器超时函数rt_thread_timeout(将当前挂起的线程加入到调度器就绪队列后重新调度),从而将线程从睡眠中唤醒。

由此可见,在软件定时器线程模式下,rt_system_timer_thread_init中初始化的定时器线程timer_thread就是rt-thread线程调度的驱动力。

RT-thread内核之系统时钟的更多相关文章

  1. 38.Linux驱动调试-根据系统时钟定位出错位置

    当内核或驱动出现僵死bug,导致系统无法正常运行,怎么找到是哪个函数的位置导致的? 答,通过内核的系统时钟,因为它是由定时器中断产生的,每隔一定时间便会触发一次,所以当CPU一直在某个进程中时,我们便 ...

  2. Zephyr学习(四)系统时钟

    每一个支持多进程(线程)的系统都会有一个滴答时钟(系统时钟),这个时钟就好比系统的“心脏”,线程的休眠(延时)和时间片轮转调度都需要用到它. Cortex-M系列的内核都有一个systick时钟,这个 ...

  3. STM32学习笔记(六) SysTick系统时钟滴答实验(stm32中断入门)

    系统时钟滴答实验很不难,我就在面简单说下,但其中涉及到了STM32最复杂也是以后用途最广的外设-NVIC,如果说RCC是实时性所必须考虑的部分,那么NVIC就是stm32功能性实现的基础,NVIC的难 ...

  4. STM32学习笔记:系统时钟和SysTick定时器

    原文:http://blog.sina.com.cn/s/blog_49cb42490100s60d.html 1.     STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI.HS ...

  5. STM32F4_RCC系统时钟配置及描述

    Ⅰ.概述 对于系统时钟应该都知道它的作用,就是驱动整个芯片工作的心脏,如果没有了它,就等于人没有了心跳. 对于使用开发板学习的朋友来说,RCC系统时钟这一块知识估计没怎么去配置过,原因在于开发板提供的 ...

  6. LPC17XX 数据手册摘要之系统时钟与功率控制

    系统时钟与功率控制 一.系统时钟 LPC17XX有三个独立的时钟振荡器,分别是主振荡器(MIAN_OSC).内部RC振荡器(IRC_OSC).实时时钟振荡器(RTC_OSC).LPC17XX时钟框图如 ...

  7. 实时时钟、系统时钟和CPU时钟的区别

    http://blog.sina.com.cn/s/blog_68f909c30100pli7.html 实时时钟:RTC时钟,用于提供年.月.日.时.分.秒和星期等的实时时间信息,由后备电池供电,当 ...

  8. stm32之Systick(系统时钟)

    Systick的两大作用: 1.可以产生精确延时: 2.可以提供给操作系统一个单独的心跳(时钟)节拍: 通常实现Delay(N)函数的方法为: for(i=0;i<x;i++) ; 对于STM3 ...

  9. μC/OS-II 的系统时钟

    简介 μC/OS-II 与大多数计算机系统一样,用硬件定时器产生一个周期为 ms 级的周期性中断来实现系统时钟,最小的时钟单位就是两次中断之间相间隔的时间,这个最小时钟单位叫做时钟节拍(Time Ti ...

随机推荐

  1. MongoDB入门---数据库&&&集合的基本操作

    MongoDB作为一种nosql的数据库,它自己本身的增伤改查还有数据库集合的创建和展示与一般的数据库较之是有一部分差别的.我们今天就来看一下MongoDB的一些基本操作.    首先呢,就是先来数据 ...

  2. xmind打开文件报错

    可以尝试使用导入 文件——导入 选择此方式打开即可.

  3. Python 通过sgmllib模块解析HTML

    """ 对html文本的解析方案-示例:在标签开始的时候检查标签中的attrs属性,解析出所有的参数的href属性值 依赖安装:pip install sgmllib3k ...

  4. Python常见的脚本汇总

    1.冒泡排序 lis = [56,12,1,8,354,10,100,34,56,7,23,456,234,-58] def sortport(): for i in range(len(lis)-1 ...

  5. 交换学生 (Foreign Exchange,UVa10763)

    题目描述: 解题思路: 开一个数组,读入一次交换两个数,如果最后数组不变,即符合匹配 #include<iostream> #include<cstdio> #include& ...

  6. spark-submit配置说明

    <Spark 官方文档>Spark配置 spark-1.6.0 原文地址 Spark配置 Spark有以下三种方式修改配置: Spark properties (Spark属性)可以控制绝 ...

  7. 告别加载dll 出错开机加载项大揭秘

    提到开机加载(load)项,大家不要以为就是系统启动(run)项.最简单的例子是,杀毒软件或者用户手动删除病毒文件后,注册表中的自动加载信息仍在,登陆系统时就会提示"加载*dll出错,系统找 ...

  8. [HNOI2018]转盘

    [HNOI2018]转盘 给你一个 \(n\) 元环, 你可以在 \(0\) 时刻从任意一个位置出发, 每一秒可以选择往后或者留在原地每个点有个参数 \(T_i\) , 当你走到 \(i\) 的时间 ...

  9. 我的linux操作习惯

    标签(空格分隔): ubuntu 最佳操作 用linux随时可能会有宕机的危险,谁知道我哪会神经病犯了呢.用deepin宕机的可能性会更高的,所以我才不得不安装一个windows做备份,然后把数据备份 ...

  10. centos配置iptables

    第一次配置前消除默认的规则 #这个一定要先做,不然清空后可能会悲剧 iptables -P INPUT ACCEPT #清空默认所有规则 iptables -F #清空自定义的所有规则 iptable ...