一、系统时钟

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. java中stream部分笔记

    Stream流表面上看起来与集合类似,允许你转换和检索数据.然而,两者却有显著的不同1.流不存储元素.它们存储在底层的集合或者按需生成2.流操作不改变他们的源数据.例如filter方法不会从一个新流中 ...

  2. C++中引用的本质分析

    引用的意义 引用作为变量别名而存在,因此在一些场合可以代替指针 引用相对于指针来说具有更好的可读性和实用性 swap函数的实现对比: void swap(int* a, int* b) { int t ...

  3. 回顾爬虫的时候的一些小TIPS

    1 json.dumps的时候默认会用ascii 所以在写入文件的时候会需要用到的指令变为json.dumps(a,ensuer_ascii=False),这样将禁止转换为ascii 然后再写入的时候 ...

  4. element-ui 分页注意事项

    <template> <div id="monitor"> 一页显示 {{currentCount}}条 当前第 {{currentPage}}页 < ...

  5. spark history server

    参考:http://blog.csdn.net/lsshlsw/article/details/44786575 为什么需要historyServer? 在运行Spark Application的时候 ...

  6. H5-基础-day01

    类选择器和ID选择器   相同点:可以应用于任何元素不同点: 1.ID选择器只能在文档中使用一次.与类选择器不同,在一个HTML文档中,ID选择器只能使用一次,而且仅一次.而类选择器可以使用多次. 2 ...

  7. NNLearning阶段性总结01

    神经网络最基本的元素与计算流程: 基本的组网原则: 神经网络监督学习的基本步骤: 初始化权值系数 提取一个样本输入NN,比较网络输出与正确输出的误差 调整权值系数,以减少上面误差——调整的方法对应不同 ...

  8. hdu1217Arbitrage(floyd+map)

    Arbitrage Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  9. 第三模块:面向对象&网络编程基础 第1章 面向对象

    我的失败与梦想(一) 我的失败与梦想之为何创办路飞学城 01-编程范式 02-面向过程编程 03-面向对象编程介绍 04-定义类与实例化出对象 05-如何使用类 06-如何使用对象 07-属性查找与绑 ...

  10. JS变量定义时连续赋值的坑!

    在定义变量时,可以将值相同的变量采用连续赋值的方式,如下代码: var a = b = c = ''; 其实这里面有一个很大很大的坑,以代码说明问题: <script language=&quo ...