驱动控制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 0
static 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 0x10070088
struct 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.驱动没有加载 lsmod
sys_open() file-->no-->mydev
3.open(fops->open)返回失败