[X]关闭

米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用

文档创建者:uisrc
浏览次数:5342
最后更新:2020-03-09
概述
      RTC(real-time clock)简称实时时钟,是日常生活中应用最为广泛的消费类电子产品之一。它为人们提供精确的实时时间或者为电子系统提供精确的时间基准,而备份电池在掉电后数据不丢失,在下次启动依旧可以重新设置当前时间给计算机。另外,可以通过RTC的周期性中断来产生闹钟,也可以在系统suspend的时候作为系统的唤醒源使用。
常见的RTC芯片主要是I2C接口和SPI接口,其中,DS1337/DS1307和PCF8563是市面上最流行、性价比最高的I2C接口芯片。如果你需要在产品中使用RTC芯片,可以在Linux内核源码中,找找是否有对应的源码,这意味着你不再需要自己编写代码,而且主线里的驱动都是测试过的,使用起来更放心一些。而对于初学者,则可以通过内核中的驱动学到更地道的编程方法,何乐而不为呢。以下是可以在内核中找到源码部分芯片:

A基于I2C接口RTC时钟芯片
* Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025
* Dallas/Maxim DS1374
* Dallas/Maxim DS1672      
* Dallas/Maxim DS3232   
* Maxim MAX6900      
* Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A  
* Intersil ISL1208
* Intersil ISL12022           
* Xicor/Intersil X1205      
* Philips PCF8563/Epson RTC8564        
* Philips PCF8583   
* ST M41T62/65/M41T80/81/82/83/84/85/87  
* TI BQ32000  
* Seiko Instruments S-35390A  
* Ramtron FM3130
* Epson RX-8581      
* Epson RX-8025SA/NB   
* EM Microelectronic EM3027
* Micro Crystal RTC

B基于SPI接口RTC时钟芯片
* Dallas DS1286
* Dallas DS1511
* Maxim/Dallas DS1553  
* Maxim/Dallas DS1742/1743
* Simtek STK17TA8
* ST M48T86/Dallas DS12887
* ST M48T35  
* ST M48T59/M48T08/M48T02  
* Oki MSM6242
* TI BQ4802
* Ricoh RP5C01   
* EM Microelectronic V3020  
       而本教程主要介绍基于I2C接口的DS1337/DS1307芯片在ZYNQ-7000上应用。 I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息,是嵌入式系统中广泛使用的一类通信协议,主要用于CPU和各种外设之间的低速数据通信。
I2C介绍
       我们知道I2C总线具备广泛的用途,比如寄存器的配置,EEPROM的使用,更重要的是I2C总线上可以挂载非常多的外设。 对于一些低速器件的访问非常节省IO资源,由于是标准的总线接口,使用起来非常方便。I2C总线是OC开路,支持双向传输,所以总线上需要上拉电阻,如下图。
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-1.jpg

I2C总线协议
       由于节课讲解的I2C是基于ZYNQ的I2C控制器,实际上可以不需要非常清楚I2C的详细时序,但是作为初学者,如果第一次学习I2C总线的,还是有必要学习下。

I2C协议把传输的消息分为两种类型的帧:
一个地址帧 :用于master指明消息发往哪个slave;
一个或多个数据帧: 由master发往slave的数据(或由slave发往master),每一帧是8-bit的数据。
注:协议要求每次放到SDA上的字节长度必须为8位,并且每个字节后须跟一个ACK位,在下面会讲到。
数据在SCL处于低电平时放到SDA上,并在SCL变为高电平后进行采样。读写数据和SCL上升沿之间的时间间隔是由总线上的设备自己定义的,不同芯片可能有差异。
I2C数据传输的时序图如下:
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-2.jpg
开始条件(start condition):
为了标识传输正式启动,master设备会将SCL置为高电平(当总线空闲时,SDA和SCL都处于高电平状态),然后将SDA拉低,这样,所有slave设备就会知道传输即将开始。如果两个master设备在同一时刻都希望获得总线的所有权,那么谁先将SDA拉低,谁就赢得了总线的控制权。在整个通信期间,可以存在多个start来开启每一次新的通信序列(communication sequence),而无需先放弃总线的控制权,后面会讲到这种机制。

地址帧(address frame):
地址帧总是在一次通信的最开始出现。一个7-bit的地址是从最高位(MSB)开始发送的,这个地址后面会紧跟1-bit的操作符,1表示读操作,0表示写操作。
接下来的一个bit是NACK/ACK,当这个帧中前面8bits发送完后,接收端的设备获得SDA控制权,此时接收设备应该在第9个时钟脉冲之前回复一个ACK(将SDA拉低)以表示接收正常,如果接收设备没有将SDA拉低,则说明接收设备可能没有收到数据(如寻址的设备不存在或设备忙)或无法解析收到的消息,如果是这样,则由master来决定如何处理(stop或repeated start condition)。

数据帧(data frames):
在地址帧发送之后,就可以开始传输数据了。Master继续产生时钟脉冲,而数据则由master(写操作)或slave(读操作)放到SDA上。每个数据帧8bits,数据帧的数量可以是任意的,直到产生停止条件。每一帧数据传输(即每8-bit)之后,接收方就需要回复一个ACK或NACK(写数据时由slave发送ACK,读数据时由master发送ACK。当master知道自己读完最后一个byte数据时,可发送NACK然后接stop condition)。

停止条件(stop condition):
当所有数据都发送完成时,master将产生一个停止条件。停止条件定义为:在SDA置于低电平时,将SCL拉高并保持高电平,然后将SDA拉高。
注意,在正常传输数据过程中,当SCL处于高电平时,SDA上的值不应该变化,防止意外产生一个停止条件。

重复开始条件(repeated start condition):
有时master需要在一次通信中进行多次消息交换(例如与不同的slave传输消息,或切换读写操作),并且期间不希望被其他master干扰,这时可以使用“重复开始条件” —— 在一次通信中,master可以产生多次start condition,来完成多次消息交换,最后再产生一个stop condition结束整个通信过程。由于期间没有stop condition,因此master一直占用总线,其他master无法切入。
为了产生一个重复的开始条件,SDA在SCL低电平时拉高,然后SCL拉高。接着master就可以产生一个开始条件继续新的消息传输(按照正常的7-bit/10-bit地址传输时序)。重复开始条件的传输时序如下图所示:
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-3.jpg
时钟拉伸(clock stretching):
有时候,低速slave可能由于上一个请求还没处理完,尚无法继续接收master的后续请求,即master的数据传输速率超过了slave的处理能力。这种情况下,slave可以进行时钟拉伸来要求master暂停传输数据 —— 通常时钟都是由master提供的,slave只是在SDA上放数据或读数据。而时钟拉伸则是slave在master释放SCL后,将SCL主动拉低并保持,此时要求master停止在SCL上产生脉冲以及在SDA上发送数据,直到slave释放SCL(SCL为高电平)。之后,master便可以继续正常的数据传输了。可见时钟拉伸实际上是利用了时钟同步的机制(见下文),只是时钟由slave产生。
如果系统中存在这种低速slave并且slave实现了clock stretching,则master必须实现为能够处理这种情况,实际上大部分slave设备中不包含SCL驱动器的,因此无法拉伸时钟。
所以更完整的I2C数据传输时序图为:
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-4.jpg
10-bit地址空间:
上面讲到I2C支持10-bit的设备地址,此时的时序如下图所示:
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-5.jpg
在10-bit地址的I2C系统中,需要两个帧来传输slave的地址。第一个帧的前5个bit固定为b11110,后接slave地址的高2位,第8位仍然是R/W位,接着是一个ACK位,由于系统中可能有多个10-bit slave设备地址的高2bit相同,因此这个ACK可能由多有slave设备设置。第二个帧紧接着第一帧发送,包含slave地址的低8位(7:0),接着该地址的slave回复一个ACK(或NACK)。
注意,10-bit地址的设备和7-bit地址的设备在一个系统中是可以并存的,因为7-bit地址的高5位不可能是b11110。实际上对于7-bit的从设备地址,合法范围为b0001XXX-b1110XXX,’X’表示任意值,因此该类型地址最多有112个(其他为保留地址[1])。
两个地址帧传输完成后,就开始数据帧的传输了,这和7-bit地址中的数据帧传输过程相同。

时钟同步和仲裁:
如果两个master都想在同一条空闲总线上传输,此时必须能够使用某种机制来选择将总线控制权交给哪个master,这是通过时钟同步和仲裁来完成的,而被迫让出控制权的master则需要等待总线空闲后再继续传输。在单一master的系统上无需实现时钟同步和仲裁。

时钟同步:
时钟同步是通过I2C接口和SCL之间的线“与”(wired-AND)来完成的,即如果有多个master同时产生时钟,那么只有所有master都发送高电平时,SCL上才表现为高电平,否则SCL都表现为低电平。

总线仲裁:
总线仲裁和时钟同步类似,当所有master在SDA上都写1时,SDA的数据才是1,只要有一个master写0,那此时SDA上的数据就是0。一个master每发送一个bit数据,在SCL处于高电平时,就检查看SDA的电平是否和发送的数据一致,如果不一致,这个master便知道自己输掉仲裁,然后停止向SDA写数据。也就是说,如果master一直检查到总线上数据和自己发送的数据一致,则继续传输,这样在仲裁过程中就保证了赢得仲裁的master不会丢失数据。
输掉仲裁的master在检测到自己输了之后也不再产生时钟脉冲,并且要在总线空闲时才能重新传输。
仲裁的过程可能要经过多个bit的发送和检查,实际上两个master如果发送的时序和数据完全一样,则两个master都能正常完成整个的数据传输。

RTC时钟DS1307介绍
DS1307是低功耗、两线制串行读写接口、日历和时钟数据按BCD码存取的时钟/日历芯片。它提供秒、分、小时、星期、日期、月和年等时钟日历数据。另外它还集成了如下几点功能:
(1)56 字节掉电时电池保持的NV SRAM 数据存储器
(2)可编程的方波信号输出
(3)掉电检测和自动切换电池供电模式
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-6.jpg
       S1307的寄存器地址空间如下,我们的代码也就是读写一下地址空间。
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-7.jpg
地址空间中详细的参数定义如下表
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-8.jpg
写时序如下:
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-9.jpg
写时序很容易理解,和我们前面写EEPROM一样,先发送器件地址为1101000,再发送寄存器的地址,之后是连续写数据。
读时序如下:
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-10.jpg
       这里读的时序有点没描述清楚,读时序前首先还要进行一次写寄存器起始地址的设置。比如代码,首先是写器件地址,并且指定标记读寄存器的其实寄存器地址为0x00,然后从标记的0x00读7个字节的数据。后面时序分析的时候再配合以上读写时序图介绍。
FPGA BD工程设计
通过EMIO的方式将PS端的IIC接口引出来
1、如下图,在ZYNQ7 Processing System IP的配置界面里,将IIC 0配置为EMIO。
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-11.jpg
2、如下图,按住Ctrl+T的组合键,将IIC_0引出来并重命名为IIC_0。

(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-12.jpg

在约束文件里添加以下内容。
set_property PACKAGE_PIN L15 [get_ports IIC_0_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC_0_sda_io]
set_property PACKAGE_PIN L14 [get_ports IIC_0_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC_0_scl_io]

配置kernel添加I2C及RTC的支持
、配置kernel,确保Device Drivers -> I2C support -> I2C Hardware Bus support->Cadence I2C Controller被选中。
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-13.jpg
2、 确保Device Drivers -> Real Time Clock界面下,确保以下选项被选中DS1337/DS1307使用的是同一份源代码。drivers/rtc/ rtc-ds1307.c,有兴趣的可以去阅读学习。
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-14.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-15.jpg
3、配置完使用save_ kernel _config.sh保存配置。

修改设备树
&i2c0 {
         clock-frequency = <400000>;
         status = "okay";
         /* DS1337 RTC module */
         Rtc0@68 {
                   compatible = "dallas,ds1337";
                   reg = <0x68>;
         };
};
编译并且部署系统到TF卡进行测试

安装RTC模块

(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-16.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-17.jpg

测试
上电启动MZ7XA-7020,从启动信息可以看到,rtc0已经可以挂载到总线上了接下的实验会教大家。
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-1.jpg
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-2.jpg
硬件时钟(Real Time Clock)和系统时钟(System Clock)是Linux系统中的两个重要的时钟。硬件时钟也被称为RTC、CMOS或BIOS时钟,指主机板上的时钟设备,通常系统断电后,由主板上的电池提供电源。系统时钟也叫内核时钟或者软件时钟,是由内核根据时间中断来进行计数的,内核时钟在系统关机的情况下是不存在的,所以,当操作系统启动的时候,内核时钟是要读取读取硬件时钟来进行时间同步,然后系统时钟就会独立于硬件钟运行。
使用date命令显示系统时间:            
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-3.jpg
date命令修改系统时间:
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-4.jpg

使用“hwclock”或“hwclock –r”命令显示硬件时钟与日期:(注意:由于此时还未设置硬件时候,故提示“low voltage detected, date/time is not reliable. “)
我正常测试的RTC模块已经设置过了
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-5.jpg

使用“hwclock –w”命令将硬件时钟调整为与目前的系统时钟一致:
其中data -s "2019-07-30 22:00" 为把系统时间设置为当前时间,这样才方便测试有对比(如果RTC模块没有修改过时钟,可以发现硬件时钟与系统时钟不一致,low voltage detected, date/time is not reliable.)
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-6.jpg
hwclock -s将系统时钟调整为与目前的硬件时钟一致
先执行 date -s "2011-02-24 22:22"把系统时钟修为2011年方便测试
现在reboot一下
细心的同学应该可以看到,在接下来的启动信息有以下信息,这就是前面说的,内核启动时会将硬件时钟同步到系统时钟。
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-8.jpg
进入系统后,我们再来看看是硬件时钟和系统时钟是不是一致。
米联客(MSXBO)osrc-lab LINUX下RTC时钟模块使用-9.jpg
参考资料:






(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-18.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-19.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-20.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-21.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-22.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-23.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-25.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-26.jpg
(米联客MSXBO)osrc-lab LINUX下RTC时钟模块使用-27.jpg

发表评论已发布 1

云海

发表于 2020-3-9 17:41:12 | 显示全部楼层

谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则