Chinaunix首页 | 论坛 | 博客
  • 博客访问: 502649
  • 博文数量: 157
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 1608
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-16 09:30
文章存档

2010年(155)

2008年(2)

我的朋友

分类: LINUX

2010-04-07 10:37:46



如果你不知道实时时钟是什么,那这篇文章你必须要仔细看了!(概念的东西我尽量详细的讲,如果还有不清楚的地方请参考专业书籍)

中的时钟可分为系统时钟和硬件时钟两种。硬件时钟可以依赖于持续电源(通常是钮扣电池)持续累计时间,而系统时间会再系统调电之后重置,所以一般linux系统再开始时会做一个系统时钟于硬件时钟同步的动作(hwclodk -w),这个我们在后面再详细解释!所谓的实时时钟简单理解起来,就是一个设备掉电(poweroff)之后的系统时钟维持模块。

好了现在我们解释清楚了实时时钟到底是个什么东西!就不难猜测这个出现的问题是什么。

       首先,我们不能不承认intel给我们带来了性能优良的处理器。各位注意,我们可不是在讨论如何攒机,我们是做嵌入式系统的把PC暂时放在一边。在嵌入式领域intel 提供给我们了xscal体系的处理器芯片也是相当不错的,现在有很多嵌入式的芯片提供内置的RTC,但是事实上并非真正的实时时钟,像手里的这款pxa270,系统调电之后RTC也同样调电重置,要她何用!

       好了现在我们明确问题是什么了?如何解决呢,内置的不行我们就只能用外置的,介绍几款不错的RTC芯片给大家!

       Rtc8564 ds1340 m41t00

       该芯片只有8个引脚,总线设备,软件时钟校准功能,包含7个数据寄存器和1个控制寄存器。列位看到这里可能觉得枯燥,但是我当时看到她只有八个寄存器时,我真的爱死她了!

从图中我们可以看到,这个芯片的时间量程!只有100年,此时你就必须考虑时间基数问题,这是后话。

总线设备的硬件连接简直是再简单不过了,就像用软件来读写设备一样的简单,我们不得不佩服那些总线通讯协议的设计者,他们今天收益,而我们受益!

       总之一句话,m41t00这个芯片已经挂在系统的总线上了!

       有些人总是心急的不的了,现在就开始编写驱动怎么样,当然可以。但是,我像用最简单的方法测试一下我们的这个八脚的小家伙!我假设你的总线驱动已经加载,否则你可以跳过这一步,或者先晚上你的系统总线驱动(那是另外一个浩瀚的工程,嘿嘿,穿别人的鞋,走自己的路,让他找去吧!)。

上载图片真是麻烦,大家下载一个Datasheet来看吧!

以下内容为软件部分,绝非全部由本人原创,如有雷同,并非巧合;但决不虚构;因为应用原理都是一样的!


呵呵,开个玩笑!

       既然是应用程序无非就是read,write。是的如果没有算法加进来的话,就是这样的,更何况这是一个测试程序!

       首先介绍一个系统总线(设备)给大家,如果有人接受不了这个概念可以先把它了解清楚再继续阅读,如果觉得自己还可以忍受一会儿的话,我们在后面的总线中给大家详细解释。

[root@Intel rtc]# ll /dev/i2c-0

这个目录就是我们的总线设备(它对应我们的总线适配器),你可以把它简单的理解为总线,我们后面的操作其实就是对总线的读和写。

        fd = open(I2C_DEV, O_RDWR);// I2C_DEV /dev/i2c-0

         printf("####i2c test device open failed####\n");

                return (-1);

        res = ioctl(fd,I2C_TENBIT,0);   //not 10bit

        res = ioctl(fd,I2C_SLAVE,CHIP_ADDR);    //设置从设备地址[6:0]

上面是打开该设备的源码,并进行了相关的设置,这里需要了解一点总线的知识,简单的给大家提两句,是工作在主从模式下的,也就是说不关是读还是写都是由工作在主模式下的设备发起的。主设备在发送的命令中包含从设备的地址,也就是上面的CHIP_ADDR,这个地址是由phips公司提供给生产设备芯片的厂商的。我们这个芯片的地址是。

打开该设备之后我们对他进行读写,这里还需要了解一点总线的知识,关于读写的时序!


在写从设备寄存器的时候,先发送的是从设备的地址,然后是要写入的寄存器的偏移地址,最后是数据,当然你可以写一个寄存器或者多个,只要给出基址就可以了;在读从设备的时候稍微复杂一点点,先要写入要读写的从设备的寄存器偏移量,然后在再读取数据!

这里有一个细节大家一定要注意,读写是由控制位决定的,由从设备地址(7位)加上1位读写控制位,组成了一个字节!

有了上面的这些介绍我们就不难理解下面的这两个读写函数:

static int read_HWclock(int fd, char buff[], int addr, int count)

{

  if(write(fd,&addr,1)!=1)        //写地址失败

        res=read(fd,buff,count);

        printf("read %d byte at 0x%x\n", res, addr);

}

static int write_HWclock(int fd, char buff[], int addr, int count)

{

        static char sendbuffer[PAGE_SIZE+1];

        memcpy(sendbuffer+1, buff, count);

        for(n=0; n

                printf("0x%x, ", sendbuffer[n]);

        res=write(fd,sendbuffer,count+1);

        printf("write %d byte at 0x%x\n", res, addr);

}

[root@Intel rtc]#./readrtc

[root@Intel rtc]#

这个测试结果显然是令人满意了,现在大可放心,这个八只脚的笑臭虫,还是很听话的!

测试结束之后,我们就可以沐浴更衣,去探讨总线驱动的问题,他是如此之复杂,以至于我们不得不静下心来,仔细的研究他的实现!

总线仅仅使用SCL、SDA两根信号线就实现了设备之间的数据交互,极大地简化对硬件资源和PCB板布线空间的占用。因此,总线被非常广泛地应用在EEPROM、实时钟、小型LCD等设备与CPU的接口中。

Linux定义了系统的驱动体系结构,在Linux系统中,驱动由3部分组成,即核心、总线驱动和设备驱动。

下面我们大致介绍一下这三部分组成以及相互联系:

核心提供了总线驱动和设备驱动的注册、注销方法,通信方法(即“algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。
总线驱动

总线驱动是对硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至直接集成在CPU内部。总线驱动主要包含了适配器数据结构、适配器的algorithm数据结构和控制适配器产生通信信号的函数。
经由总线驱动的代码,我们可以控制适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ACK等。
设备驱动

设备驱动是对硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的适配器上,通过适配器与CPU交换数据。设备驱动主要包含了数据结构和,我们需要根据具体设备实现其中的成员函数。

说了上面这些东西,大家应该都比较了解了,只是比较抽象,其实理解了这个层次结构和相互之间的联系,就不难读懂代码.我们看一下PC上的设备,加深一下印象。

在Linux 2.6内核中,所有的设备都被在sysfs文件系统中显示,存在于目录,以适配器地址和芯片地址的形式列出,如:

$ tree /sys/bus/i2c/
/sys/bus/i2c/
|-- devices
|   |-- 0-0048 -> ../../../devices/legacy/i2c-0/0-0048
|   |-- 0-0049 -> ../../../devices/legacy/i2c-0/0-0049
|   |-- 0-004a -> ../../../devices/legacy/i2c-0/0-004a
|   |-- 0-004b -> ../../../devices/legacy/i2c-0/0-004b
|   |-- 0-004c -> ../../../devices/legacy/i2c-0/0-004c
|   |-- 0-004d -> ../../../devices/legacy/i2c-0/0-004d
|   |-- 0-004e -> ../../../devices/legacy/i2c-0/0-004e
|   `-- 0-004f -> ../../../devices/legacy/i2c-0/0-004f
`-- drivers
    |-- i2c_adapter
    `-- lm75
        |-- 0-0048 -> ../../../../devices/legacy/i2c-0/0-0048
        |-- 0-0049 -> ../../../../devices/legacy/i2c-0/0-0049
        |-- 0-004a -> ../../../../devices/legacy/i2c-0/0-004a
        |-- 0-004b -> ../../../../devices/legacy/i2c-0/0-004b
        |-- 0-004c -> ../../../../devices/legacy/i2c-0/0-004c
        |-- 0-004d -> ../../../../devices/legacy/i2c-0/0-004d
        |-- 0-004e -> ../../../../devices/legacy/i2c-0/0-004e
        `-- 0-004f -> ../../../../devices/legacy/i2c-0/0-004f

 今天看到自己以前的帖子没有沉下去,很是欢心鼓舞,索性再拿点东西跟大家分享,看完帖子之后一定要顶呀!呵呵


阅读(4757) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-06-21 11:29:53

呵呵,转载,不是他写的,确实不咋着

chinaunix网友2010-06-04 17:39:28

真怀疑你的语言能力!@!