NUC970系列CPU和STM32一样自带RTC备份寄存器,供掉电前保存重要数据使用,容量是16x32bit=64byte
修改rtc驱动,增加nuc970_rtc_ioctl函数
struct nuc970_rtc_spr {
unsigned int num;
unsigned int value;
};
#define RTC_SPR_SET_DATA 0x0801
#define RTC_SPR_GET_DATA 0x0802
#define REG_RTC_SPR0 0x40 //RTC备份寄存器地址
static int nuc970_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
{
struct nuc970_rtc *rtc = dev_get_drvdata(dev);
struct nuc970_rtc_spr rtc_sprs;
void __user *uarg = (void __user *) arg;
int *err;
unsigned char nums;
err = check_rtc_spr_access_enable(rtc);
if (IS_ERR(err))
{
return PTR_ERR(err);
}
if (copy_from_user(&rtc_sprs, uarg, sizeof(rtc_sprs)))
{
return -EFAULT;
}
nums = rtc_sprs.num;
switch (cmd)
{
case RTC_SPR_SET_DATA:
//printk("K: set rtc spr%d, value:%x\n", nums, rtc_sprs.value);
rtc_reg_write(rtc, REG_RTC_SPR0+nums*4, rtc_sprs.value);
break;
case RTC_SPR_GET_DATA:
rtc_sprs.value = rtc_reg_read(rtc, REG_RTC_SPR0+nums*4);
//printk("K: get rtc spr%d, value:%x\n", nums, rtc_sprs.value);
rtc_sprs.num = nums;
if (copy_to_user(uarg, &rtc_sprs, sizeof(rtc_sprs)))
{
return -EFAULT;
}
break;
}
return 0;
}
static struct rtc_class_ops nuc970_rtc_ops = {
.ioctl = nuc970_rtc_ioctl,
.read_time = nuc970_rtc_read_time,
.set_time = nuc970_rtc_set_time,
.read_alarm = nuc970_rtc_read_alarm,
.set_alarm = nuc970_rtc_set_alarm,
.alarm_irq_enable = nuc970_alarm_irq_enable,
};
测试demo
#include <stdio.h>
#include <string.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <signal.h>
struct nuc970_rtc_spr {
unsigned int num;
unsigned int value;
};
#define RTC_SPR_SET_DATA 0x0801
#define RTC_SPR_GET_DATA 0x0802
#define FILE_DEV "/dev/rtc0"
int main (int argc, char* argv[])
{
int i=0;
int fd = -1;
int ret = -1;
struct nuc970_rtc_spr rtc_spr;
memset(&rtc_spr, 0x00, sizeof(rtc_spr));
printf("---------------------\n");
fd = open (FILE_DEV, O_RDWR);
if (fd < 0)
{
printf("### open "FILE_DEV" fail!\n");
return -1;
}
//测试读RTC SPR0寄存器的值
rtc_spr.num = 0;
if ((ret = ioctl(fd, RTC_SPR_GET_DATA, &rtc_spr)) < 0)
{
printf("### ioctl "FILE_DEV" get rtc spr%d data faile %d\n", rtc_spr.num, ret);
return ret;
}
printf("### read rtc spr%d data=0x%lx\n\n", rtc_spr.num, rtc_spr.value);
//测试写数据到RTC SPR0寄存器
rtc_spr.num = 0;
rtc_spr.value += 0xA5;
printf("### write rtc spr%d data=0x%lx\n\n", rtc_spr.num, rtc_spr.value);
if ((ret = ioctl(fd, RTC_SPR_SET_DATA, &rtc_spr)) < 0)
{
printf("### ioctl "FILE_DEV" set rtc spr%d data faile %d\n",rtc_spr.num, ret);
return ret;
}
//测试读RTC SPR1寄存器的值
rtc_spr.num = 1;
if ((ret = ioctl(fd, RTC_SPR_GET_DATA, &rtc_spr)) < 0)
{
printf("### ioctl "FILE_DEV" get rtc spr%d data faile %d\n", rtc_spr.num, ret);
return ret;
}
printf("### read rtc spr%d data=0x%lx\n\n", rtc_spr.num, rtc_spr.value);
//测试写数据到RTC SPR1寄存器
rtc_spr.num = 1;
rtc_spr.value += 0xA6;
printf("### write rtc spr%d data=0x%lx\n\n", rtc_spr.num, rtc_spr.value);
if ((ret = ioctl(fd, RTC_SPR_SET_DATA, &rtc_spr)) < 0)
{
printf("### ioctl "FILE_DEV" set rtc spr%d data faile %d\n",rtc_spr.num, ret);
return ret;
}
return 0;
}