一、driver
RTC使用内核I2C子系统、RTC子系统、SYSFS接口技术。
1. i2c子系统
a.本设备采用16寄存器地址,在构造消息时地址为word;
struct i2c_msg {
__u16 addr; /* slave address */
__u16 flags;
__u16 len; /*msg length */
__u8 *buf; /*pointer to msg data */
};
按照时序图构建消息,从机地址注册设备时已确定,flags需要注意读/写;
static intisl12027_read_regs(struct i2c_client*client, uint16_t reg,
uint8_t *data,size_t n)
{
uint8_t buf[2]={reg>>8,reg&0xff};
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,/*write*/
.len = 2,
.buf = buf
}, /* setup read ptr */
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = n,
.buf = data
}
};
int ret;
ret = i2c_transfer(client->adapter, msgs,ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&client->dev,"%s: read error, ret=%d\n",
__func__, ret);
return -EIO;
}
return 0;
}
static intisl12027_write_reg(struct i2c_client*client,
uint16_t reg,uint8_t val)
{
int ret;
uint8_tdata[]={reg>>8,reg&0xff,val};
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = 3,
.buf = data
}
};
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret != ARRAY_SIZE(msgs)) {
dev_err(&client->dev,
"%s: ret=%dregH=%02x, regL=%02x,val=%02x\n",
__func__, ret, data[0],data[1],data[2]);
return -EIO;
}
return 0;
}
b.
2. RTC子系统
Linux系统把各种机制或者子系统抽象出来,达到低耦合,易扩展,这里暂且按组件来理解,下面是RTC常和那些“组件”组合来完成,device成为他们的纽带。
这里以I2C接口RTC为例:
Linux把按分层思想构建RTC子系统(其它子系统也一样),采用面向对象思想实现。
a. 分层思想
Linux系统实现了对用户的接口,设备访问、SYS访问,PROC访问,并提供了抽象接口,已达到上层不变,接口中使用了多态使得可以支持不同的设备,
rtc->ops->read_time(rtc->dev.parent,tm);
在创建对象时动态绑定:
rtc_device_register(isl1208_driver.driver.name,
&client->dev, &isl1208_rtc_ops,
THIS_MODULE);
这个是构造函数来创建对象,他实现动态绑定;
rtc->id = id;
rtc->ops = ops;
rtc->owner = owner;
rtc->max_user_freq = 64;
rtc->dev.parent = dev;
rtc->dev.class = rtc_class;
rtc->dev.release = rtc_device_release;
b. 面向对象