驱动控制RTC
-
用户需求:写一个RTC时钟控制的驱动,实现RTC显示年月日时分秒到用户端
-
驱动需求:设备:RTC模块 功能:打印显示
-
寄存器操作:
-
原理图: 设备–>pin–>设备控制芯片
驱动需求 --> 设备需求
-
芯片手册:设备控制芯片–>寄存器
-
驱动程序
/*===============================================
* 文件名称:modRtc.c
* 创 建 者: memories
* 创建日期:2023年07月10日
* 描 述:have a nice day
================================================*/
//头文件
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "rtc.h"#define MA 300
#define MI 0static dev_t no = 0;
static unsigned count = 1;
static const char *name = "mydev";
static struct cdev mydev;
static int *rtccon = NULL;
static int *bcdsec = NULL;
static int *bcdmin = NULL;
static int *bcdhour = NULL;
static int *bcddayweek = NULL;
static int *bcdday = NULL;
static int *bcdmon = NULL;
static int *bcdyear = NULL;void addr_map(void)
{rtccon = ioremap(RTCCON,4);bcdsec = ioremap(BCDSEC,4);bcdmin = ioremap(BCDMIN,4);bcdhour = ioremap(BCDHOUR,4);bcddayweek = ioremap(BCDDAYWEEK,4);bcdday = ioremap(BCDDAY,4);bcdmon = ioremap(BCDMON,4);bcdyear = ioremap(BCDYEAR,4);
}void dev_init(void)
{writel(readl(rtccon)|(0x1),rtccon);writel(0x46,bcdsec);writel(0x23,bcdmin);writel(0x14,bcdhour);writel(0x1,bcddayweek);writel(0x11,bcdday);writel(0x4,bcdmon);writel(0x023,bcdyear);}void addr_unmap(void)
{iounmap(rtccon);iounmap(bcdsec);iounmap(bcdmin);iounmap(bcdhour);iounmap(bcddayweek);iounmap(bcdday);iounmap(bcdmon);iounmap(bcdyear);
}struct RTC mydata(void)
{struct RTC rtc;rtc.sec = readl(bcdsec);rtc.min = readl(bcdmin);rtc.hour = readl(bcdhour);rtc.dayweek = readl(bcddayweek);rtc.year = readl(bcdyear);rtc.mon = readl(bcdmon);rtc.day = readl(bcdday);return rtc;
}/*
时间设置之后会一直走,不用open和release
int myopen (struct inode *pi, struct file *pf)
{printk("open success\n");return 0;
}
int myrelease (struct inode *pi, struct file *pf)
{printk("release success\n");writel(readl(rtccon)&~(0x1),rtccon);return 0;
}
*/
ssize_t myread(struct file *pf, char __user *rbuf, size_t len, loff_t *poff)
{int ret = -1;struct RTC rtc = mydata();ret = copy_to_user(rbuf,&rtc,sizeof(struct RTC));if(ret !=0 ){printk("copy is failed\n");return -1;}return len;
}static struct file_operations myfops={// .open = myopen,// .release = myrelease,.read = myread,
};
//初始化
int myinit(void)
{int ret;//向上内核no = MKDEV(MA,MI);//注册设备号ret = register_chrdev_region(no,count,name);if(ret !=0){printk("reg is error\n");return -1;}//设备操作初始化cdev_init(&mydev,&myfops);//添加设备ret = cdev_add(&mydev,no,count);if(ret != 0){unregister_chrdev_region(no,count);return -1;}//向下驱动//1.映射addr_map();//2.寄存器初始化dev_init();printk("my init is ok\n");return 0;
}
//退出
void myexit(void)
{//删除设备cdev_del(&mydev);//注销设备号unregister_chrdev_region(no,count);//解除映射addr_unmap();printk("my exit is ok\n");return ;
}
module_init(myinit);
module_exit(myexit);
//信息
MODULE_LICENSE("GPL");
应用程序
/*===============================================
* 文件名称:rtc.c
* 创 建 者: memories
* 创建日期:2023年07月10日
* 描 述:have a nice day
================================================*/
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include "rtc.h"int main(int argc, char *argv[])
{ int fd = open("/dev/mydev",O_RDWR);if(fd < 0){printf("open is failed\n");return -1;}while(1){int ret;struct RTC rtc;ret = read(fd,&rtc,sizeof(struct RTC));if(ret < 0){perror("read");return -1;}printf("2%03x-%x-%x %x %x:%x:%x\n",rtc.year,rtc.mon,rtc.day,rtc.dayweek,rtc.hour,rtc.min,rtc.sec);sleep(1);}close(fd);return 0;
}
/*===============================================
* 文件名称:rtc.h
* 创 建 者: memories
* 创建日期:2023年07月10日
* 描 述:have a nice day
================================================*/
#ifndef __rtc_H_
#define __rtc_H_#define RTCCON 0x10070040
#define BCDSEC 0x10070070
#define BCDMIN 0x10070074
#define BCDHOUR 0x10070078
#define BCDDAYWEEK 0x10070080
#define BCDDAY 0x1007007C
#define BCDMON 0x10070084
#define BCDYEAR 0x10070088struct RTC{int sec;int min; int hour; int dayweek; int year; int mon;int day; }; #endif
打开设备文件失败的原因:
1.文件没有创建 ls-l /dev/mydev 检查文件有没有和设备号open("/dev/mydev")
2.驱动没有加载 lsmodsys_open() file-->no-->mydev
3.open(fops->open)返回失败