s3c6410 RTC driver——读取实时时间信息

开发环境:Ubuntu 14.0

开发板内核版本:Linux 3.0

The Real Time Clock (RTC) unit can be operated by the backup battery when the system power is off. The data include the time by second, minute, hour, date, day, month, and year. The RTC unit works with an external 32.768 KHz crystal and can perform the alarm function.

下面是RTC相关的18个寄存器

s

在头文件中的定义

在mach/map.h里面

自己定义一个header file 方便使用(一层封装的思想)

EOF_rtc.h

/**************************************************
code writer :   EOF
code date   :   2014.08.26
e-mail      :   jasonleaster@gmail.comcode purpose:This header file is used for ...It's convenient to use this MACRO but not
address number directly.**************************************************/
#ifndef _EOF_RTC_H
#define _EOF_RTC_H#include <mach/map.h> /* for 'S3C64XX_PA_RTC' */#define RTC_CON       (S3C64XX_PA_RTC + 0x40)#define RTC_SECOND_REG  (S3C64XX_PA_RTC + 0x70)
#define RTC_MINUTE_REG  (S3C64XX_PA_RTC + 0x74)
#define RTC_HOUR_REG    (S3C64XX_PA_RTC + 0x78)
#define RTC_DATE_REG    (S3C64XX_PA_RTC + 0x7C)
#define RTC_DAY_REG (S3C64XX_PA_RTC + 0x80)
#define RTC_MONTH_REG   (S3C64XX_PA_RTC + 0x84)
#define RTC_YEAR_REG    (S3C64XX_PA_RTC + 0x88)/*
** second minute hour day month and year.
** There are six messages waited to be read.
*/
#define MESSAGE     6#define DEVICE_NAME    "rtc_time"
/*
**  create four device for fun, demo for one driver but drive different devices
*/
#define DEVICE_NUM  1
#define PORT_NUM    36
#define RTC_PORT_BASE   S3C64XX_PA_RTC#define RTC_MAJOR 0 /*by dynamical *//*
**  It's fantastic to use a structure to abstract a device!
*/
struct rtc_dev
{struct cdev cdev;struct mutex mutex;/*** used for storing time message */int buf[1024];
};#endif

rtc_time.c

/************************************************************
code writer :   EOF
code date   :   2014.08.26
e-mail      :   jasonleaster@gmail.com
code file   :   rtc_time.ccode purpose:This is code is for RTC-driver in s3c6410-ARM.#BUG-1! 2014.08.27  afternoonI am sorry about there is a bug waited to be fixed up.When we print out the "day-message", we can't get the
right one.It always print out digital number '1'.I don't know
what happens...If you could fix it up, please touch me by e-mail.
Thank you.@BUG-1 fixed upI mixed up with DATE and DAY in register.Now it work
correctly.If you still find something wrong with my code, please
touch me. Thank you.************************************************************/#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>#include <linux/cdev.h>      /* for 'struct cdev'*/
#include <linux/kdev_t.h> /* for 'MAJOR MINOR' */
#include <linux/fs.h>
#include <linux/kernel.h> /* for 'printk()' */
#include <linux/slab.h>       /* for 'kmalloc()'*/
#include <linux/types.h>  /* for 'ssize_t'*/
#include <linux/proc_fs.h>
#include <asm/io.h>       /* for 'inl & outl'*/
#include <asm/uaccess.h>  /* for 'copy_to_user'*/
#include <linux/ioport.h> /* for 'request_region()' 'ioremap()' */#include <linux/device.h> /* for 'struct class'*/#include "EOF_rtc.h"#define DEBUGunsigned int rtc_major  =  RTC_MAJOR;
unsigned int rtc_minor  =  0;unsigned long t_msg_addr[MESSAGE] =
{RTC_SECOND_REG,RTC_MINUTE_REG,RTC_HOUR_REG,RTC_DATE_REG,RTC_MONTH_REG,RTC_YEAR_REG
};module_param(rtc_major,int,S_IRUGO);
module_param(rtc_minor,int,S_IRUGO);MODULE_AUTHOR("EOF");
MODULE_LICENSE("Dual BSD/GPL");/* allocated in 'void rtc_init(void)' */
struct rtc_dev* rtc_devices;
struct class* rtc_class;static int rtc_proc_show(char* buf,char** start,off_t offset,int count,int* eof,void* data)
{#ifdef DEBUGprintk(KERN_ALERT "calling rtc_proc_show...\n");
#endifchar k_output[1024];struct rtc_dev* dev = rtc_devices;int device_num = 0;int length = 0;int temp = 0;int foo  = 0;if(mutex_lock_interruptible(&dev->mutex)){return -ERESTARTSYS;}for(device_num = 0;device_num < DEVICE_NUM;device_num++){length += sprintf(k_output+length,"### rtc%d ###\n",device_num);for(temp = 0; temp < MESSAGE;temp++){foo = readl(ioremap(t_msg_addr[temp],sizeof(int)));length += sprintf(k_output+length," temp: %d time: %d\n",temp, ((foo & 0xF0)>>4)*10 + (foo & 0x0F) );}    }printk(KERN_ALERT "%s\n",k_output);*eof = 1;mutex_unlock(&dev->mutex);return 0;
}static void rtc_create_proc(void)
{struct proc_dir_entry * entry;entry    = create_proc_read_entry("rtc_reader",0,NULL,rtc_proc_show,NULL);if(!entry){printk(KERN_ALERT "line:%d 'proc_create_read_entry()' failed!\n",__LINE__);}
}static void rtc_remove_proc(void)
{remove_proc_entry("rtc_reader",NULL);
}ssize_t rtc_read(struct file* filp,char __user* buf,const size_t count,loff_t* f_pos)
{
#ifdef DEBUGprintk(KERN_ALERT "rtc_read ing... using ioremap...");
#endifstruct rtc_dev* dev = filp->private_data;int temp  = 0;int ret     = 0;if(mutex_lock_interruptible(&dev->mutex)){return -ERESTARTSYS;}else{
#ifdef DEBUGprintk(KERN_ALERT "Lock in rtc_read!\n");
#endif}for(temp = 0; temp < MESSAGE;temp++){/*** Hey,penguins...Attention! Do not use the physic address directly.** You shoult remap it into virtual addres by 'ioremap()'.*///dev->buf[temp] = inl(t_msg_addr[temp]);dev->buf[temp] = readl(ioremap(t_msg_addr[temp],sizeof(int)));
#ifdef DEBUGprintk(KERN_ALERT "dev->buf[%d] : %x\n",temp,dev->buf[temp]);
#endif} if((ret = copy_to_user(buf,dev->buf,count))){printk(KERN_ALERT "copy_to_user failed!\n");temp = temp - ret;goto out_read;}out_read:mutex_unlock(&dev->mutex);
#ifdef DEBUGprintk(KERN_ALERT "Lock released rtc_read!\n");
#endifreturn temp;
}ssize_t rtc_write(struct file* filp,const char __user* buf,size_t count,loff_t* f_ops)
{
#ifdef DEBUGprintk(KERN_ALERT "writing rtc ...\n");
#endifstruct rtc_dev* dev = filp->private_data;int ret = 0;int temp = 0;if(mutex_lock_interruptible(&dev->mutex)){return -ERESTARTSYS;}if((ret = copy_from_user(dev->buf,buf,sizeof(*(dev->buf)) * MESSAGE))){temp = temp - ret;goto out_write;}for(temp = 0; temp < MESSAGE;temp++){outl(dev->buf[temp],(ioremap(t_msg_addr[temp],sizeof(int))) );}  out_write:mutex_unlock(&dev->mutex);return 0;
}int rtc_open(struct inode* inode,struct file* filp)
{
#ifdef DEBUGprintk(KERN_ALERT "rtc_open ing...!\n");
#endifstruct rtc_dev* dev;dev = container_of(inode->i_cdev,struct rtc_dev,cdev);filp->private_data = dev;return 0;
}int rtc_release(struct inode * inode, struct file* filp)
{
#ifdef DEBUGprintk(KERN_ALERT "rtc Released!\n");
#endifreturn 0;
}struct file_operations rtc_fops =
{.owner =  THIS_MODULE,.read   =  rtc_read,/*** It's dangerous and unnecessory to write something into RTC's register, the company which created your 'RTC' have finished 'write-work'.Generally, you shouldn't change it.** But I also implement a method that how to write message** into RTC's register.*/.write   =  rtc_write,.open =  rtc_open,.release= rtc_release,
};static void rtc_setup_cdev(struct rtc_dev* dev,int indev)
{int err = 0;int dev_num = MKDEV(rtc_major,rtc_minor + indev);cdev_init(&dev->cdev,&rtc_fops);dev->cdev.owner  =  THIS_MODULE;dev->cdev.ops    =  &rtc_fops;err =  cdev_add(&dev->cdev,dev_num,1);if(err){printk(KERN_ALERT "Error in adding rtc%d, err value:%d\n",indev,err);}else{
#ifdef DEBUGprintk(KERN_ALERT "rtc_%d setted!\n",indev);
#endif}
}void rtc_clean(void)
{int temp = 0;dev_t    dev_num = 0;dev_num = MKDEV(rtc_major,rtc_minor);if(rtc_devices){for(temp = 0;temp > DEVICE_NUM;temp++){cdev_del(&rtc_devices[temp].cdev);device_destroy(rtc_class,MKDEV(MAJOR(dev_num),temp));
#ifdef DEBUGprintk(KERN_ALERT "rtc%d!\n",temp);
#endif}kfree(rtc_devices);}rtc_remove_proc();unregister_chrdev_region(dev_num,DEVICE_NUM);release_region(RTC_PORT_BASE,PORT_NUM);}int rtc_init(void)
{/* get our needed resource */if(!request_region(RTC_PORT_BASE,PORT_NUM,DEVICE_NAME)){printk(KERN_ALERT "rtc: can't request address:%p\n",(void*)RTC_PORT_BASE);return -ENODEV;}int ret = 0;int temp = 0;dev_t dev_num = 0;ret = alloc_chrdev_region(&dev_num,rtc_minor,DEVICE_NUM,DEVICE_NAME);rtc_major = MAJOR(dev_num);rtc_class = class_create(THIS_MODULE,DEVICE_NAME);if(ret < 0){printk(KERN_ALERT "rtc: can't get major %d\n",rtc_major);return ret;}/* allocate the device -- we can't have them static, as the number* can be specified at load time*/   rtc_devices = kmalloc(DEVICE_NUM*sizeof(struct rtc_dev),GFP_KERNEL);if(!rtc_devices){ret = -ENOMEM;goto fail;}memset(rtc_devices,0,DEVICE_NUM * sizeof(struct rtc_dev));/* Initialize the device */for(temp = 0;temp < DEVICE_NUM;temp++){mutex_init(&rtc_devices[temp].mutex);rtc_setup_cdev(&rtc_devices[temp],temp);device_create(rtc_class,NULL,(dev_num + temp),NULL,"rtc_%d",temp);}rtc_create_proc();#ifdef DEBUGprintk(KERN_ALERT "rtc registed!\n");
#endifreturn 0;fail:rtc_clean();return 0;
}module_init(rtc_init);
module_exit(rtc_clean);

测试程序

/*********************************************************************
code writer : EOF
code date : 2014.08.16
code file : rtc_test.c
e-mail    : jasonleaster@gmail.comcode purpose:This is a demo for user how to use RTC device driver.You should know that data store in RTC register as BCD-code.
If you want to represent it as deciminal, we could transform two-bits
BCD-code into deciminal number by this way:Deciminal number = ((BCD-code&0xF0)>>4)*10+(BCD-code)&0x0F;If there is something wrong with my code,
please touch me by e-mail. Thank you.*********************************************************************/#include <stdio.h>
#include <fcntl.h>int main()
{int buf[10];char output[BUFSIZ] = {0,};int fd = 0;int counter = 0;if((fd = open("/dev/rtc_0",O_RDONLY)) < 0){printf("open failed!\n");return 0;}if(read(fd,buf,sizeof(buf)) <= 0){printf("read failed\n");goto failed;}counter += sprintf(output+counter,"Time now: ");counter += sprintf(output+counter,"Year: 20%d ", ((buf[5]&0xF0)>>4)*10 + (buf[5]&0x0F));counter += sprintf(output+counter,"month: %d ",  ((buf[4]&0xF0)>>4)*10 + (buf[4]&0x0F));counter += sprintf(output+counter,"day: %d ",    ((buf[3]&0xF0)>>4)*10 + (buf[3]&0x0F));counter += sprintf(output+counter,"hour: %d ",   ((buf[2]&0xF0)>>4)*10 + (buf[2]&0x0F));counter += sprintf(output+counter,"minute: %d ", ((buf[1]&0xF0)>>4)*10 + (buf[1]&0x0F));counter += sprintf(output+counter,"second: %d\n",((buf[0]&0xF0)>>4)*10 + (buf[0]&0x0F));printf("%s\n",output);failed:close(fd);return 0;
}

和rtc_time.c里面注释说的一样,我遇到了一个BUG,目前还不知道怎么搞定他,如果高手路过恳请指导修正

很明显有一个有错的地方,今天是8月27日,但是他怎么都是print 8.1...

这里是date输出的结果和我直接debug打印结果(BCD玛)的对比

day对应的是dev->bug[3],这里BCD码是1....

update: 2014.08.27 19:01:33

替换了最新的EOF_rtc.h 和rtc_time.c

修复了之前的“day-bug”

s3c6410 RTC driver——读取实时时间信息 LDD3 ELDD 学习笔记相关推荐

  1. [书]x86汇编语言:从实模式到保护模式 -- 第九章 硬中断,使用RTC芯片实现实时时间的显示;软中断,使用BIOS中断实现键盘输入的读取和显示

    PART 1 >> 使用BIOS中断实现键盘输入的读取和显示 ; File: c09_2.asm ; Date: 20191222; =========================== ...

  2. Linux时间管理和定时学习笔记

    Linux时间管理和定时 时间的概念 时间的计量 Linux系统中的时间管理 Linux内核对时间的维护 获取当前时间 时间格式转换 将时间转换为字符串 指定格式的字符串 获取高精度时间 微秒 纳秒 ...

  3. cs客户端 实时权限_【CS学习笔记】7、SMBbean的作用

    0x00 SMB Beacon 简介 SMB Beacon 使用命名管道通过一个父 Beacon 进行通信.这种对等通信对同一台主机上的 Beacon 和跨网络的 Beacon 都有效.Windows ...

  4. 信息系统管理工程师学习笔记

    1.1.1 信息系统概述 1.1信息系统的概念 1.系统:各组成部分能够互相作用,互相依赖,具有特定的功能,共同组成一个有机整体就是系统. 2.信息系统:用以收集.处理.存储.分发信息的互相关联的组件 ...

  5. coap 返回版本信息_CoAP协议学习笔记

    CoAP是一种应用层协议,运行于UDP协议之上,非常小巧,最小的数据包仅4字节. CoAP协议定义 CoAP协议的交互模型与HTTP的客户端/服务端模型类似.然而,在M2M的交互场景中,CoAP的目标 ...

  6. 奇安信病毒检测中心 2022年第二季度App收集个人信息检测报告 学习笔记 附下载地址

    奇安信 2022年第二季度App收集个人信息检测报告 下载地址 2022年第二季度 APP收集个人信息 检测报告 奇安信 病毒响应中心 研究背景 随着互联网和移动设备的发展,手机已成为人人都拥有的设备 ...

  7. python读取html内容 dom获取_python学习笔记十三 JS,Dom(进阶篇)

    JS介绍 JavaScript 是属于网络的脚本语言!JavaScript 被数百万计的网页用来改进设计.验证表单.检测浏览器.创建cookies,以及更多的应用:JavaScript 是因特网上最流 ...

  8. java当前时间转化毫秒_Java学习笔记-时间相关类

    1. Date类: java.util.Date 时间原点:1970年1月1日00:00:00(中国+8小时) System.currentTimeMillis() 计算当前时间到原点经历的毫秒数 无 ...

  9. mysql查询当前时间和用户_MySQL学习笔记(3) - 查询服务器版本,当前时间,当前用户...

    IIC驱动移植在linux3.14.78上的实现和在linux2.6.29上实现对比(deep dive) 首先说明下为什么写这篇文章,网上有许多博客也是介绍I2C驱动在linux上移植的实现,但是笔 ...

  10. 量子计算--复习+量子信息--铺垫(学习笔记)

       本次,我对前面所学的算符进行一定的拓展并对接下来的量子信息的学习做一些铺垫. 一.些概念的复习和拓展    在前面,我对量子计算的一些概念进行了简单的讲解,而且对一些概念描述的并不完整,所以此次 ...

最新文章

  1. 渗透测试之全方位信息收集神器 instarecon
  2. boost::exception_test::throw_test_exception<T>的测试程序
  3. php中用for循环制作矩形,PHP中for循环语句的几种变型
  4. 使用CXF发布WebService服务简单实例
  5. 华为android强刷系统下载地址,华为P6S官方rom固件刷机包下载_华为P6S原版系统强刷升级包...
  6. 第三周读书笔记《程序员修炼之道》
  7. 我用VS2015 开发webapp (1) 需求、目的、配置
  8. 433MHZ LORA扩频模块于PDA的完美结合
  9. vscode的code runner不生成临时文件
  10. IT界有哪些书是必看的?
  11. 解决安装Visio2016 和office 2016不能兼容问题
  12. uni-app注册自动获取短信信息
  13. 使用计算机的安全事项,电脑安全使用注意事项
  14. Unity3d绑定键盘弹出UI
  15. 马斯洛需求层次与产品的关系
  16. 学大数据的你可能还不知道机器学习对软件还有这些影响?
  17. 如何禁止pdf复制修改打印
  18. 企业建网站需要注意什么SEO问题
  19. MapReduce实现平均分计算
  20. 20个公开课网址大全,值得收藏、慢慢学习

热门文章

  1. linux su - 用户名,在Linux中,su命令 (切换用户)
  2. Introduction to Computer Networking学习笔记(二):字节顺序
  3. dll封装成activex控件_Qt编写自定义控件26-平铺背景控件
  4. Oracle11g exp 1445,oracle11g 导出表报EXP-00011:table不存在。
  5. java applog_个人app如何收集用户日志
  6. 动态库的隐式链接和显示链接
  7. Dynamic Rankings(整体二分)
  8. React-leaflet在ant-design pro中的基本使用
  9. Android Gradle 完整指南(转)
  10. The Beauty of DirectX 11 (3) --- constant buffer, buffered/structure buffer