rtems系统时钟原理

RTEMS 操作系统 ​RTEMS,全称为 ​​(多处理器系统的实时执行体),是一个开源的实时操作系统(RTOS)​,最初由美国军方资助开发,目标是满足航空航天、国防等高安全、高性能、强实时性领域中的嵌入式系统需求。随着发展,RTEMS 已成为一个通用、高度可移植、模块化、支持多处理器架构的实时操作系统,广泛用于航空航天、工业控制、医疗设备、电信和嵌入式实时系统中。选择 RTEMS 的理由说明✅ ​高实时性与确定性​适用于任务响应要求极高的系统,如飞行控制✅ ​多核与多处理器支持​原生 SMP,适合现代多核 SoC。 阅读详情

 

一:从应用看原理

二:从RTEMS4.6.99.3-GP32说起

三:RTEMS4.6.99.3-GP32启动系统时钟代码流程

四:关于TICK

五:怎么实现年,月,日,时,分,秒

六:TICK的发生

七:定时器实现TICK计数

八:结束

 

一:从应用看原理

     每个系统都有一种时钟来支持,常常听到的某某系统支持“时分复用”(亦或叫“轮转调度”),TCP/IP中超时重传,我们每天用的手机能准确计算年,月,日,时,分,秒(手机中都带操作系统的,motorola的A1200就是带linux操作系统的),还有Linux中常看到的Jifferies。。。。,这些都是通过系统时钟来实现的。

二:从RTEMS4.6.99.3-GP32说起

当然,这种系统时钟是需要硬件支持,象rtems46.99.3中的GP32 bsp就是通过2400的timer4来实现的。(注意,既然系统把timer4用来做系统时钟,timer4就不能用来做其他的定时操作了)

那么,rtems中是如何实现这种系统时钟的呢?下面,我以rtems4.6.99.3中的gp32为例来阐述这个问题:(注意,gp32是针对sumsung的2400,我这里以sumsung的2410讲解)

RTEMS中如果要用到时钟,

      首先,需要在应用程序中定义系统配置文件。如,在GP32自带的例子ticker中,(../testsuites/samples/ticker/system.h)就有如下语句:

      #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER

      系统就根据这条语句启动系统时钟。那么系统是怎么根据这条语句启动系统时钟的呢?请看其脉络:

三:RTEMS4.6.99.3-GP32启动系统时钟代码流程

 

   通过一层层的调用,系统时钟已布置好了。但,至此,仅仅是理清了整个rtems代码的组织方式。那么,rtems是怎样用2400的timer4实现系统时钟的呢?

 

四:关于TICK

这就涉及到定时器了的原理了。

定时器是通过中断来实现的,在函数Clock_driver_support_initialize_hardware()中,通过设置2400的timer4的相关寄存器。(因为,我在2410上调试的,所以函数Clock_driver_support_initialize_hardware()中我加了rTCFG0 = rTCFG0 & ~(0xffffff) | 0x000f00 ;)即可定义系统多长时间tick一次,也即rtems的时间精度(粒度)。其中,BSP_Configuration.microseconds_per_tick就是在应用程序中配置的值,单位是微秒。如果,希望系统的精度达到1毫秒,则应定义BSP_Configuration.microseconds_per_tick = 1000。在pppd例程中定义的是BSP_Configuration.microseconds_per_tick = 10000,即10ms。因此,可知系统每10ms发生一次tick。而在ticker例程中,并没有定义CONFIGURE_MICROSECONDS_PER_TICK,此时系统采用默认配置,其值为10ms。(参考confdefs.h)。

 五:怎么实现年,月,日,时,分,秒

我们每天用电脑,但想没想过电脑右下角的时钟是这么实现计时的呢?还有,我们每天用的手机其时间是这么实现的呢?下面,通过rtems中的ticker例程来剖析其中奥秘。

在ticker例程的init.c中,定义了一个rtems_time_of_day类型的结构体time,并初始化为    time.year   = 1988;

  time.month  = 12;

  time.day    = 31;

  time.hour   = 9;

  time.minute = 0;

  time.second = 0;

  time.ticks  = 0;

接着,通过调用rtems_clock_set函数把time结构体传给内核,作为系统时钟的时间基准。内核中,根据先前定义的CONFIGURE_MICROSECONDS_PER_TICK换算成“每秒产生的tick数”进行计数。以CONFIGURE_MICROSECONDS_PER_TICK = 10000为例,则系统时钟“每秒产生的tick数”为100。因此,系统时钟每tick一次,time.ticks加1,当达到100时向秒进位,即time.second加1(同时,time.ticks复位到0)。Time.second计数到60时又向前进一,即time.minute 加1(同时,time.second复位到0)。以此类推,直到time.year,这个就不用我多说了。

而,系统通过调用rtems_clock_get函数即可获得当前时间值。这样一个系统时钟就运行起来了。

 

集以上所说,其实还有一个根本性的问题,不知有人产生过疑问没有?

追本逐末,时钟的根源是tick,那么tick是这么产生的呢?

 

 六:TICK的发生

 

Tick是通过中断实现的。

回到上面的脉络图,在函数Install_clock中调用的Clock_driver_support_install_isr这个函数,就是注册时钟中断号。Clock_driver_support_install_isr这个函数调用了系统函数BSP_install_rtems_irq_handler,而BSP_install_rtems_irq_handler传给内核一个很重要的参数clock_isr_data,它是个结构体,内容如下:

rtems_irq_connect_data clock_isr_data = {BSP_INT_TIMER4,

                                         (rtems_irq_hdl)Clock_isr,

                                         clock_isr_on,

                                         clock_isr_off,

                                         clock_isr_is_on,

                                         3,     /* unused for ARM cpus */

                                         0 };   /* unused for ARM cpus */

这个结构体有两个很重要的成员,即BSP_INT_TIMER4和Clock_isr。前者告诉BSP_install_rtems_irq_handler函数,要注册的中断源是timer4;后者是一个中断句柄(句柄就是函数的入口地址),用中断术语描述就叫ISR(interrupt service routine中断服务例程),当timer4中断发生时,即跳到Clock_isr执行。我们再来看Clock_isr里面的内容。

rtems_isr Clock_isr(rtems_vector_number vector)

{

  Clock_driver_ticks += 1;

  Clock_driver_support_at_tick();

  rtems_clock_tick();

}/*为了简洁起见,我去掉了注释和非执行语句*/

函数Clock_driver_support_at_tick();主要完成中断寄存器的复位清零动作,不然第二次中断就不能发生了。

全局变量Clock_driver_ticks就是我们要找的答案,看到没有,每发生一次中断,它的值加1。

再来看函数rtems_clock_tick();其实这个函数才是真正的为系统时钟服务。跟进去发现它调用了_TOD_Tickle_ticks();函数,这个函数是个内敛函数位于cpukit/rtems/src/clocktick.c。它做了两件事情#define _TOD_Tickle_ticks() /

  _TOD_Current.ticks++; /

  _Watchdog_Ticks_since_boot++

注意了,这里也有个全局变量加1的动作,其实,这才是我们要找的真正的答案。系统时钟实现计时就是通过取当前tick值_TOD_Current.ticks。

这里又会产生一个疑惑,在发生中断时两个全局变量都做了加1的动作,那么time.ticks计数到100后向前进1而自己清零的动作在哪里呢?这个问题说来又话长了,我这里只告诉大家其代码在哪些位置,具体实现你们去琢磨。

   函数rtems_initialize_executive_early(cpukit/sapi/src/exinit.c)-à _TOD_Handler_initialization(cpukit/score/src/coretod.c)。

 

七:定时器实现TICK计数

   RTEMS中时间的准确性依赖于tick的实现,而tick是依赖于定时器4(timer4)的实现,timer4每发生一次中断tick实现加1的计数。Timer4是怎么实现定时器的中断的呢?

   回到上面的脉络图

   #define Clock_driver_support_initialize_hardware() /

  do { /

        uint32_t cr; /

        uint32_t freq,m,p,s; /

        /*set prescale to 15*/ /       

        rTCFG0 = rTCFG0 & ~(0xffffff) | 0x000f00 ; /

        /* set MUX for Timer4 to 1/16 */ /

        cr=rTCFG1 & 0xFFF0FFFF; /

        rTCFG1=(cr | (3<<16)); /

        freq = get_PCLK(); /

        /* set TIMER4 counter, input freq=PLCK/16/16Mhz*/ /

        freq = (freq /16)/16; /

        rTCNTB4 = ((freq / 1000) * BSP_Configuration.microseconds_per_tick) / 1000; /

        /*unmask TIMER4 irq*/ /

        rINTMSK&=~BIT_TIMER4; /

        /* start TIMER4 with autoreload */ /

        cr=rTCON & 0xFF8FFFFF; /

        rTCON=(cr|(0x6<<20)); /

        rTCON=(cr|(0x5<<20)); /

    } while (0)

   要弄懂定时器的工作原理,需要搞清楚三个量

   定时器的输入频率 freq

   定时器的缓冲计数器TCNTB(内部有一个同名的递减计数器TCNT)

   定时器的计数比较器TCMPB(内部有一个同名的递减计数器TCMP,Timer4中没有这个寄存器)

   定时器有个输入频率,这个输入频率的来源是PCLK(PCLK的频率来自与板子上的晶振),通过rTCFG0,rTCFG1两个寄存器即可设置PCLK的分频参数(针对s3c2410来说,PCLK有50.7M,不能把这么高的频率输入给定时器,而要进行分频),之后即可得到定时器4的输入频率freq = PCLK/16/16。以PCLK= 50.7M记,freq = 198046HZ,即1秒发生198046次脉冲。

   定时器的计数器TCNT根据脉冲频率计数,每发生一次脉冲减1;

   TCNT递减到0,则触发中断(TCNT从TCNTB中装载初始值,开始下一轮计数)。

   定时公式:

   T  = { 1 / freq} * TCNTB

   如果BSP_Configuration.microseconds_per_tick = 10000,则刚好能实现每10ms发生一次中断(tick)。  

   注意:TCMPB在调制脉冲(PWM)时才有用。

总结,在RTEMS中,tick是维系整个系统时间的根本,多任务的分时复用,各种超时动作,重传动作,都是通过tick来实现的。这里的tick就如Linux中的Jifferies。

   至此,RTEMS系统时钟原理介绍完毕!

 

 

 

 

50、实时嵌入式操作系统:标准、开源系统与虚拟机技术解析 本文深入解析了实时嵌入式操作系统的多个核心技术,包括异步与列表导向的I/O机制、基于POSIX标准的时钟与定时器功能、线程取消机制及其清理处理程序。文章介绍了主流开源实时操作系统如eCos、µClinux、RT-Linux、RTAI和RTEMS的特点与应用场景,并探讨了虚拟机技术的基本概念、工作原理及虚拟机器监视器(VMM)在处理器状态虚拟化中的关键作用。同时分析了VMM在资源隔离、硬件利用率提升方面的优势,以及性能开销、安全和兼容性等挑战。最后总结了实时嵌入式系统在工业自动化、航空航天、医疗设备和汽车电子 阅读详情

相关推荐

ue4 角色奔跑/冲刺/蹲下 /蹲走 动作切换蓝图

序列:文章分为4部分: 一、准备工作+简单的蓝图连线 二、编写“行走” 混合空间 三、编写“蹲下”混合空间 四、合成2个动画,设置动画蓝图 —————————————— 一、准备工作 下载“动画初学者包”,添加到项目! 主要文件: 打开BP_playerCharacter,组价——添加组件,找到“摄像机”,“机臂” 没有找到就去其他项目复制过来 ———————————— 手写人物的移动,也可以在...

凉城古梦猫扑街的博客 4862

RTEMS 介绍

为什么需要操作系统? 1.计算机是由CPU、内存、磁盘、显卡、声卡等许许多多设备组成的,而且这些设备的厂商众多,品种繁多,而且不同厂商生产的同种设备虽然完成同种功能,但是具体细节却存在千差万别;2.为了正确地管理和使用这些设备来实现具体的应用,这样程序员就得了解和掌握各种设备的工作原理。而且对于同种设备,由于不同的硬件厂商在实现细节上的差异使得程序员再次陷入了复杂的硬件控制的深渊。 3.在硬件的基...

有趣的人生 一半是山川湖海 一半是初心情怀 3088

量子密钥分发系统的设计与实现(二):光路子系统初步讨论

本文主要对量子密钥分发系统中的光路子系统方案进行了讨论。

量子领域相关话题 2406

RTEMS介绍

为什么需要操作系统?   1.计算机是由CPU、内存、磁盘、显卡、声卡等许许多多设备组成的,而且这些设备的厂商众多,品种繁多,而且不同厂商生产的同种设备虽然完成同种功能,但是具体细节却存在千差万别; 2.为了正确地管理和使用这些设备来实现具体的应用,这样程序员就得了解和掌握各种设备的工作原理。而且对于同种设备,由于不同的硬件厂商在实现细节上的差异使得程序员再次陷入了复杂的硬件控制

andy205214的专栏 1028

瑞芯微RK3568开发板实战:Android11系统parameter.txt文件配置全解析(附常见问题排查)

本文深入解析了瑞芯微RK3568开发板在Android 11系统下parameter.txt文件的配置要点与实战技巧。作为BootLoader启动阶段的核心蓝图,该文件决定了硬件初始化、分区布局及电源管理。文章详细拆解了身份标识、GPIO控制(PWR_HLD)、命令行参数及分区表等关键字段的配置逻辑,并针对RK3568平台与Android 11特性提供了专项适配策略,最后附带了启动失败、分区异常等常见问题的深度排查方法。

php55的博客 895

ResNet与注意力机制:深度学习中的强强联合

本文详细介绍了ResNet和注意力机制的基本原理,并探讨了如何将两者结合,以提升网络的性能。通过在ResNet中引入注意力机制,网络可以自适应地调整特征图的重要性,从而更加关注于关键区域,提升模型的性能。实验结果表明,引入注意力机制后,ResNet的性能得到了显著提升。未来,随着注意力机制的不断发展,我们可以期待更多创新的网络架构和训练方法,进一步提升深度学习模型的性能。

2401_82355416的博客 1782

RTEMS 控制台驱动

UART 是一种串行,全双工,低速,异步通信方式(没有时钟线)UART 需要 RX、TX 两根线帧格式:起始位(逻辑0) + 数据位(5到9位,常见8位) + 校验位 + 停止位(逻辑1,1到2位)传输数据以字节为单位,传输速度由波特率控制(常见9600、115200)串口的波特率表示传输的速率,具体是指每秒钟传输的二进制位数。

Ning Yang 的博客 239

YOLOv9分割改进 ,YOLOv9分割改进主干网络为华为EfficientNet,助力涨点

EfficientNet论文中研究了卷积网络的缩放和,并证明对深度,宽度和分辨率复合缩放的重要性,因此精度和效率更好。为了阐述相关的原理,我们提出了简单有效的复合缩放方法,使得模型缩放具有一定设计准则,同时兼顾了模型的效率。我下文将 YOLOv9 分割模型改进主干网络为 EfficientNet 融合网络结构。论文地址代码地址下文都是手把手教程,跟着操作即可添加成功把环境配置好,数据集处理好,训练基本能成功,创作不易,请帮忙点一个爱心,关注我,带你不挂科!

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 937

rtems网络移植-实现网卡驱动

经过两周的调试,终于初步实现网卡的发送功能。 在这里参考了uboot的beaglebone网卡驱动和《tcp/ip详解卷二》 1、在前几篇博文中,讲解了网卡的mdio初始化过程,那么网卡lan8710a是如何与am335x处理器通信的呢? 首先看一张连接图: 我们都知道osi七层协议,最底下的是物理层和数据链路层,也就是mac和phy。有一部分处理器是自带mac层,也就是只

hahachenchen789的博客 5357

PTP(确时间协议,Precision Time Protocol)时间同步

主时钟定期发送带预估发送时间 t1 的报文(若支持硬件时间戳,实际 t1​ 由后续的Follow_Up报文携带)。所有设备启动后通过协商选举出唯一主时钟(Grandmaster),其余设备自动成为从时钟(Slave)。:从时钟记录接收时间 t2,随后向主时钟发送Delay_Req并记录发送时间 t3​。若使用支持PTP的交换机,可修正报文在交换机内的驻留时间,进一步提升精度。从时钟根据offset调整本地时钟,实现与主时钟同步。动态调整本地时钟,抵消传输延迟和时钟漂移。(或通过BMCA自动当选)。

努力努力努力 1303

Open3D 进阶(22)间接平差法拟合空间曲线

空间曲线拟合在电力线三维重建中有着广泛的应用,本文利用python使用间接平差法对三维空间曲线的拟合进行代码实现。

点云侠的博客 1057

uboot研读笔记 | 00 - 嵌入式Linux系统中Bootloader的作用和基本运行原理

1. 嵌入式Linux系统开发架构 一个嵌入式Linux的系统的架构如下图: 软件程序开发中,从下往上每一次的作用依次为: Bootloader:将硬件初始化,并将内核引导起来; Linux Kernel:定制、裁剪之后的Linux内核; 根文件系统:提供文件系统,更好的使用存储空间; 设备驱动:完成设备操作,并向上层软件提供设备的调用接口; 应用程序:Linux系统编程、网络编程、shell...

Mculover666的博客(嵌入式) 3789

windows中搭建sonic云真机环境/云真机环境搭建-基于docker容器部署

基于Windows系统搭建Sonic远程云真机环境实现通过浏览器操作手机端系统

雾林小妖的博客 1015

实时系统的双时钟:OSAL 定时器与时间基 Timer/Timebase API 完全解析

OSAL(cFS Core Flight System 操作系统抽象层)为飞行软件提供了一套精心设计的**定时器(Timer)**与**时间基(Timebase)**API。很多新手会困惑:为什么 NASA 的 OSAL 要提供两套"时钟"?本文带你彻底搞懂 [osapi-timer.h](https://link.gitcode.com/i/fcf2009f3eef620099ad55730ba

gitblog_00629的博客 328

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

从点亮屏幕到串口打印:手把手带你完成龙芯1B开发板第一个程序测试

本文详细介绍了龙芯1B开发板从开发环境搭建到串口输出的完整流程,包括工具链配置、RTOS选择、串口通信设置及第一个程序的编写与调试。通过实战演示,帮助开发者快速上手国产MIPS架构开发板,解决常见问题并优化性能。

weixin_30321709的博客 475

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Bootloader及u-boot简介/u-boot系统启动流程

Bootloader及u-boot简介 Bootloader代码是芯片复位后进入操作系统之前执行的一段代码,主要用于完成由硬件启动到操作系统启动的过渡,从而为操作系统提供基本的运行环境,如初始化CPU、堆栈、存储器系统等。Bootloader 代码与CPU 芯片的内核结构、具体型号、应用系统的配置及使用的操作系统等因素有关,其功能类似于PC机的BIOS程序。由于Bootloader和CPU及电路

maopig的专栏 1848

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

如何在浏览器中运行完整的Linux系统?jor1k在线模拟器深度解析

你是否想过在浏览器中直接运行完整的Linux操作系统,无需安装虚拟机或双系统?jor1k在线模拟器正是这样一个革命性的工具,它通过纯JavaScript实现的OpenRISC 1000处理器模拟器,让你在浏览器中就能体验完整的Linux环境。这个开源项目不仅支持网络连接、文件操作,还能模拟多核处理器,为学习、开发和测试提供了前所未有的便利。 ## 技术原理解析:JavaScript如何模拟完整C

gitblog_00641的博客 623

U-boot源代码全分析系列(基于PowerPC)-1

一、概述     U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目,是从FADSROM、8xxROM、PPCBOOT逐步发展演化而来的。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源

JuanA1的专栏 8558

U-boot简介及常用命令说明

使用u-boot开发一些项目有一段时间了,对u-boot也更加熟悉了。以前经常想u-boot存在的意义到底是啥呢?百科上说U-Boot的作用是系统引导。恩?引导系统?具体什么含义?u-boot在实际开发中还有什么具体作用?好吧,如果你对这些问题感兴趣,是吧。………………

bahutou, 嵌入式系统解决方案 1万+

U-boot源代码全分析系列(基于PowerPC)

一、概述     U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目,是从FADSROM、8xxROM、PPCBOOT逐步发展演化而来的。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。但是U-Boot不仅仅支持嵌入式Li

qingfengtsing的专栏 3103
上一篇: compile arm-rtems-gcc and rtems's bsp on 2410
下一篇: Linux下批量修改文件时间
control_tech
博客等级 码龄17年 53粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值