+ -
当前位置:首页 → 问答吧 → 如何为pcf8563增加alarm功能呢?驱动该怎么写呢?

如何为pcf8563增加alarm功能呢?驱动该怎么写呢?

时间:2010-07-15

来源:互联网

pcf8563是一块i2c的实时时钟芯片,它还有个附加功能是alarm。
内核驱动里有实现rtc功能的pcf8563的驱动,但是没有实现alarm功能。

我想在用户空间通过一设备文件来控制pcf8563的alarm功能,驱动应该怎么写呢?
可以按照rtc里pcf8563的实现再创建一个pcf8563的i2c_client吗?
还是可以利用现有的i2c资源(rtc pcf8563已经插入内核),获取pcf8563这个i2c_client,然后在这个之上再扩展功能?

对驱动这块不是太了解,所以想听听大家的意见。
谢谢!

作者: jetking   发布时间: 2010-07-15

回复 jetking


    在rtc_pcf8563.c中,,,
      static const struct rtc_class_ops pcf8563_rtc_ops = {
        .read_time        = pcf8563_rtc_read_time,
        .set_time        = pcf8563_rtc_set_time,
      };现在只是定义了read_time和set_time,,
      那要增加alarm功能怎么办?
     先看看struct rtc_class_ops 是如何定义的
struct rtc_class_ops {
          int (*open)(struct device *);
        void (*release)(struct device *);
        int (*ioctl)(struct device *, unsigned int, unsigned long);
        int (*read_time)(struct device *, struct rtc_time *);
        int (*set_time)(struct device *, struct rtc_time *);
        int (*read_alarm)(struct device *, struct rtc_wkalrm *);
        int (*set_alarm)(struct device *, struct rtc_wkalrm *);       
              int (*proc)(struct device *, struct seq_file *);
        int (*set_mmss)(struct device *, unsigned long secs);
        int (*irq_set_state)(struct device *, int enabled);
        int (*irq_set_freq)(struct device *, int freq);
        int (*read_callback)(struct device *, int data);
};
其中的两个函数指针read_alarm和set_alarm就是用来实现alarm功能的,,LZ只需要添加这两个回调函数就可以了。。。

至于这两个函数是如何被调用到的,,这就涉及到字符驱动的东西了,,在 drivers/rtc/rtc-dev.c中的一个函数rtc_dev_ioctl()
这个函数就是设备的ioctl接口了,在这个函数中可以配置RTC的所有功能,,,,LZ可以跟踪一下流程,还是很简单的。

作者: wmmy2008   发布时间: 2010-07-15

谢谢楼上的!
这个做法是重新实现pcf8563的rtc驱动。

我把pcf8563编译进内核了。所以现有的设备没有办法使用新的驱动。

后来找到一个办法:
在驱动里,通过 i2c_get_adapter得到adapter,然后通过list_for_each 每个adapter的client,比较每个client->driver->id来获取pcf8563的i2c client, id号见“include/linux/i2c-id.h”这样我就可以在我自己的驱动里实现timer和alarm功能。

作者: jetking   发布时间: 2010-07-16

回复 jetking


    如果是那样的话,LZ根本就不需要自己写模块驱动了。。只需要在userspace 直接open这个i2c设备,然后直接读写time, alarm设备地址即可,LZ可以看看
drivers/i2c/i2c-dev.c 文件定义的open ,read,write;不过这样用户用起来很不爽,所以要在pcf8563.c中定义read_time和set_time方法,这种接口用户读写时间会
很方便。

作者: wmmy2008   发布时间: 2010-07-16

本帖最后由 wmmy2008 于 2010-07-16 15:42 编辑

回复 jetking


    刚才还没注意,其实你这种做法是不行的。。。
   首先你可以用 i2c_get_adapter找到设备对应的adapter ,,但是你是一定找不到i2c_client的,,
     你看看i2c_client的定义:
  struct i2c_client {
        unsigned short flags;                /* div., see below                */
        unsigned short addr;                /* chip address - NOTE: 7bit        */
                                        /* addresses are stored in the        */
                                        /* _LOWER_ 7 bits                */
        char name[I2C_NAME_SIZE];
        struct i2c_adapter *adapter;        /* the adapter we sit on        */
        struct i2c_driver *driver;        /* and our access routines        */
        struct device dev;                /* the device structure                */
        int irq;                        /* irq issued by device                */
        struct list_head list;                /* DEPRECATED */
        struct completion released;
};
所以就算你晓得i2c_adapter 也找不到i2c_client 。。
还有i2c_client 是在i2cdev_open()的时候在动态建立的,在i2cdev_release()就释放掉了,,也就是说在设备open的时候创建,在设备close的时候销毁...
那么请问你是如何得到i2c_client呢?

作者: wmmy2008   发布时间: 2010-07-16

用/dev/i2c/0设备在用户空间读写也是一种方法,但是对该操作的ioctl不是太了解,就没有从这条路走。

i2c_adatper一直存在,我是一个嵌入式设备,实现的是cpu上的i2c,该驱动是编译进kernel的。i2c_client表示i2c设备,在i2c_adapter结构中是以链表来组织的,具体楼上可以看一下i2c_adapter的结构。

例如rtc pcf8563的模块插入的时候,i2c_adapter就会加入一个pcf8563的i2c_client,生存周期我认为是伴随该模块的。无论你open or close /dev/i2c/0,总是能通过hwclock来操作该rtc设备。

你说i2c_client在i2cdev_open时动态建立,我猜测是用户空间操作i2c设备时,内核需要一个i2c_client来承载对于指定地址的i2c设备的操作。

例如我在用户空间里对地址0x51(pcf8563的i2c地址)发送数据,i2cdev实现部分会生成一个i2c_client实例来操作,但不影响原来rtc pcf8562的这个i2c_client。应该说是不同的功能生成了不同的i2c_client,但却指向了同一个设备。

我只是从你的话中猜测内核的做法,有空我去看一实现。
欢迎讨论!
谢谢!

作者: jetking   发布时间: 2010-07-16

回复 jetking


    不好意思,很久以前看过的I2C架构了,有些忘了。。
   刚才又简单看了一下,这两个client确实用处不一样,在i2c_attach_client()函数中有个函数list_add_tail(&client->list, &adapter->clients);
   所以是可以先找到的adapter,然后遍历下面挂的所有client,这是可以的。。
但是我觉得你这样子做有点绕,,因为I2C架构已经为我们提供了设备操作方法接口,你可以看看 drivers/i2c/i2c-dev.c 上面我们可以read,write,ioctl配置读写地址等很多功能,,如果你再去实现这些东西就没的好大的意思了,有现成的直接用好些。。

作者: wmmy2008   发布时间: 2010-07-16

你说的对,可以直接通过/dev/i2c/0来操作,绕路了。

作者: jetking   发布时间: 2010-07-17

热门下载

更多