Cloud6410 RTC driver -- read Real-Time Information <ldd3 & eldd Study Notes>

Source: Internet
Author: User
Tags sprintf
Cloud6410 RTC driver -- read Real-Time Information

Development Environment: Ubuntu 14.0

Development Board kernel version: 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.

The following are the 18 registers related to RTC.


Definition in header file

In Mach/map. H

Customize a header file for ease of use (one-layer encapsulation idea)


/**************************************************code writer :EOFcode date   :2014.08.26e-mail    :[email protected]code purpose:This header file is used for ...It's convenient to use this MACRO but notaddress 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_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 MESSAGE6#define DEVICE_NAME"rtc_time"/***create four device for fun, demo for one driver but drive different devices */#define DEVICE_NUM1#define PORT_NUM36#define RTC_PORT_BASES3C64XX_PA_RTC#define RTC_MAJOR0 /*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


/************************************************************code writer :EOFcode date   :2014.08.26e-mail    :[email protected]code file   :rtc_time.ccode purpose:This is code is for RTC-driver in s3c6410-ARM.#BUG!I 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 knowwhat happens...If you could fix it up, please touch me by e-mail.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_DAY_REG,RTC_MONTH_REG,RTC_YEAR_REG};module_param(rtc_major,int,S_IRUGO);module_param(rtc_minor,int,S_IRUGO);module_param(t_msg_addr,unsigned long,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");#endifstruct 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(buf+length,"### rtc%d ###\n",device_num);for(temp = 0; temp < MESSAGE;temp++){foo = readl(ioremap(t_msg_addr[temp],sizeof(int)));length += sprintf(buf+length," temp: %d time: %d\n",temp, ((foo & 0xF0)>>4)*10 + (foo & 0x0F) );}}*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] : %d\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_tdev_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_tdev_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);

Test procedure

/*********************************************************************code writer : EOFcode date : 2014.08.16code file : rtc_test.ce-mail  : [email protected]mail.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;}

As mentioned in rtc_time.c, I encountered a bug and I don't know how to fix it yet. If the master passes by, please instruct me to fix it.

Obviously, there is something wrong with it. Today is July 22, but how is it all print...

Here is the comparison between the output result of date and the result of my direct debug printing (BCD Ma ).

Day corresponds to Dev-> bug [3]. Here the BCD code is 1 ....

Cloud6410 RTC driver -- read Real-Time Information <ldd3 & eldd Study Notes>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.