linux系统32bit的Y2038问题规避方案

背景

产品客户需要时间能够设置到2038以后,所以需要去解决这个问题,通过查阅资料可知,linux内核在5.6的版本就已经修复了2038的问题,但是目前产品使用的是3.10的版本,所以这个问题仍然存在,但是未能找到针对3.10版本的补丁,自己去修改的话,因为修改时间相关的比较多,没有太大的把握。
针对上面的问题,和根据产品情况,有下面两个方案的可行性比较高:

  1. 直接操作rtc时间,摒弃linux系统本身的接口去获取时间,就不受linux系统本身时间存储位数的限制了
  2. 通过网络同步时间
    本文章讲述的是方式一。

实现原理

	修改rtc驱动源码接口,直接读取和设置rtc的时间,这边脱离了linux内核的限制

代码实现

关键修改,现在使用的rtc芯片是rv-8263-c7:
static int rtc_drv_open(struct inode *inode, struct file *file)
{		
	// printk("%s %d %s\n",__FILE__,__LINE__,__FUNCTION__);
	
	return 0;
}

static ssize_t rtc_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
    // printk("%s %d %s\n",__FILE__,__LINE__,__FUNCTION__);
    // int val;	
	// copy_from_user(&val, buf, count); //	copy_to_user();
    // printk("val = %d\n",val);
    // if(val == 1)
    // {
    //     for(int i = 0;i<6;i++)
    //         midea_code[i] = 0xff;
    // }
	int time[7];
	copy_from_user(time, buf, sizeof(time)); 
	int tm_sec,tm_min,tm_hour,tm_mday,tm_wday,tm_mon,tm_year;

	tm_sec = time[0];
	tm_min = time[1];
	tm_hour = time[2];
	tm_mday = time[3];
	tm_wday = time[4];
	tm_mon = time[5];
	// tm_year = time[6];
	tm_year = time[6]-1900;
	// printk("time->tm_year=%d time->tm_mon=%d time->tm_wday=%d time->tm_mday=%d \
	// time->tm_hour=%d time->tm_min=%d  time->tm_sec=%d\n",tm_year,tm_mon,\
	// tm_wday,tm_mday,tm_hour,tm_min,tm_sec);

	u8 regs[7];
	int ret;
	u8 buf1[1];
	/*置1*/
	ret = pcf85063_i2c_read_regs(rv8263_client, PCF85063_REG_CTRL1,buf1, 1);
	if (ret < 0) {
		dev_err(&rv8263_client->dev, "can't read PCF85063_REG_CTRL1 reg\n");
		return ret;
	}
		
	buf1[0] |= (1<<5);

	ret = pcf85063_i2c_write_regs(rv8263_client, PCF85063_REG_CTRL1, buf1, 1);
	if (ret < 0) {
		dev_err(&rv8263_client->dev, "can't set PCF85063_REG_CTRL1 reg\n");
		return ret;
	}

	/* hours, minutes and seconds */
	regs[0] = bin2bcd(tm_sec) & 0x7F; /* clear OS flag */

	regs[1] = bin2bcd(tm_min);
	regs[2] = bin2bcd(tm_hour);
	/* Day of month, 1 - 31 */
	regs[3] = bin2bcd(tm_mday);

	/* Day, 0 - 6 */
	regs[4] = tm_wday & 0x07;

	/* month, 1 - 12 */
	regs[5] = bin2bcd(tm_mon + 1);

	/* year and century */
	regs[6] = bin2bcd(tm_year - 100);
	
	ret = pcf85063_i2c_write_regs(rv8263_client, PCF85063_REG_SC, regs,
					PCF85063_WATCH_SECTION_LEN);
	if (ret < 0)
		return ret;
	/*置0*/
	ret = pcf85063_i2c_read_regs(rv8263_client, PCF85063_REG_CTRL1,buf1, 1);
	if (ret < 0) {
		dev_err(&rv8263_client->dev, "can't read PCF85063_REG_CTRL1 reg\n");
		return ret;
	}
		
	buf1[0] &= (~(1<<5));

	ret = pcf85063_i2c_write_regs(rv8263_client, PCF85063_REG_CTRL1, buf1, 1);
	if (ret < 0) {
		dev_err(&rv8263_client->dev, "can't set PCF85063_REG_CTRL1 reg\n");
		return ret;
	}


    return 0;
}


static ssize_t rtc_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{

	// printk("%s %d %s\n",__FILE__,__LINE__,__FUNCTION__);	
	int tm_sec,tm_min,tm_hour,tm_mday,tm_wday,tm_mon,tm_year;
	int time[7];	
	
	int ret;
	u8 regs[PCF85063_WATCH_SECTION_LEN] = { 0, };


	ret = pcf85063_i2c_read_regs(rv8263_client, PCF85063_REG_SC , regs,
					PCF85063_WATCH_SECTION_LEN);
	if (ret < 0) {
		dev_err(&rv8263_client->dev, "%s: reading RTC section failed\n",
			__func__);
		return ret;
	}
	tm_sec = bcd2bin(regs[0] & 0x7F);
	tm_min = bcd2bin(regs[1] & 0x7F);
	tm_hour = bcd2bin(regs[2] & 0x3F);/* rtc hr 0-23 */
	tm_mday =bcd2bin(regs[3] & 0x3F);
	tm_wday = regs[4] & 0x07;
	tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
	tm_year = bcd2bin(regs[6]);
	tm_year += 100;

	time[0] = tm_sec;
	time[1] = tm_min;
	time[2] = tm_hour;
	time[3] = tm_mday;
	time[4] = tm_wday;
	time[5] = tm_mon;
	time[6] = tm_year+1900;
	// printk("%s %d %s\n",__FILE__,__LINE__,__FUNCTION__);	
	// printk("time->tm_year=%d time->tm_mon=%d time->tm_wday=%d time->tm_mday=%d \
	// time->tm_hour=%d time->tm_min=%d  time->tm_sec=%d\n",tm_year,tm_mon,\
	// tm_wday,tm_mday,tm_hour,tm_min,tm_sec);

	ret = copy_to_user(buf, time, sizeof(time));
	// printk("%s %d %s\n",__FILE__,__LINE__,__FUNCTION__);	

	return  0;
}

static struct file_operations rtc_drv_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   rtc_drv_open,     
	.write	=	rtc_drv_write,
    .read   = 	rtc_drv_read,   
};

int major;
static int pcf85063_probe(struct i2c_client *client,
			  const struct i2c_device_id *id)
{
	struct rtc_device *rtc;
	int rc = 0;
	u8 buf[1];

	rv8263_client = client;
	
	// printk("%s %d %s\n",__FILE__,__LINE__,__FUNCTION__);
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
		return -ENODEV;

	rtc = devm_rtc_device_register(&client->dev, client->name,
					&pcf85063_rtc_ops, THIS_MODULE);

	if (IS_ERR(rtc))
		return PTR_ERR(rtc);

	i2c_set_clientdata(client, rtc);

	/*修改之处*/
	rc = pcf85063_i2c_get_sr(client, buf);
	if (rc < 0) {
		dev_err(&client->dev, "RTC chip is not present\n");
		return rc;
	}
	rc = pcf85063_i2c_read_regs(client, PCF85063_REG_CTRL1,buf, 1);
	if (rc < 0) {
		dev_err(&client->dev, "can't read PCF85063_REG_CTRL1 reg\n");
		return rc;
	}
	buf[0] &= 0;
	rc = pcf85063_i2c_write_regs(client, PCF85063_REG_CTRL1, buf, 1);
	if (rc < 0) {
		dev_err(&client->dev, "can't set PCF85063_REG_CTRL1 reg\n");
		return rc;
	}

	rc = device_create_file(&client->dev, &dev_attr_reg_value);

	major = register_chrdev(0, "rtc_drv", &rtc_drv_fops); // 注册, 告诉内核
	rtc_cls = class_create(THIS_MODULE, "rtc_drv");
    rtc_device = device_create(rtc_cls, NULL, MKDEV(major, 0), NULL, "rtc1"); /* /dev/gpio_midea */
	return 0;
}
主要修改是增加了read/write接口直接对rtc寄存器进行操作。也附上完整代码
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值