微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 6.Ricoboard开发板上RTC模块简单分析和使用

6.Ricoboard开发板上RTC模块简单分析和使用

时间:10-02 整理:3721RD 点击:
一、基础知识

1.      概念
RTC是real-time clock的缩写,其主要用途就是产生一个独立运行的计时器,Linux或者Windows系统启动后需要从这个计时器中读取时间,来设置系统时间。RTC具有断电保存的特性,防止因为意外断电导致系统时间混乱.

2.      硬件设备

2.1  I2c接口设备

Dallas/MaximDS1307/37/38/39/40, ST M41T00, EPSON RX-8025

Dallas/MaximDS1374 Dallas/Maxim DS1672      Dallas/Maxim DS3232   

MaximMAX6900      

Ricoh R2025S/D,RS5C372A/B, RV5C386, RV5C387A  

Intersil ISL1208Intersil ISL12022           

Xicor/IntersilX1205      

PhilipsPCF8563/Epson RTC8564        PhilipsPCF8583   

STM41T62/65/M41T80/81/82/83/84/85/87  

TI BQ32000  

SeikoInstruments S-35390A  

Ramtron FM3130

EpsonRX-8581       Epson RX-8025SA/NB   

EMMicroelectronic EM3027

Micro CrystalRTC

2.2  SPI接口设备

PC-style 'CMOS'

Dallas DS1286Dallas DS1511

Maxim/DallasDS1553  Maxim/Dallas DS1742/1743

Simtek STK17TA8

ST M48T86/DallasDS12887 ST M48T35  STM48T59/M48T08/M48T02  

Oki MSM6242

TI BQ4802

RicohRP5C01   

EMMicroelectronic V3020  

2.3  CPU自带设备

ARM AMBA PL030RTC ARM AMBA PL031 RTC

NS2816 RTC

二、RTC驱动架构

1.      核心文件

l  myir_ricoboard.dts和am4372.dtsi文件在arch/arm/boot/dts文件夹下,设置rtc设备树数据

l  rtc-omap.c       cpu提供的与rtc设备相关的驱动,与硬件层和上层交互的函数。

l  /include/linux/rtc.h rtc基础数据结构

l  Class.c  rtc类注册文件,rtc相关最早加载,并主动通过rtc_dev_init加载rtc-dev.c,通过rtc_sysfs_init加载rtc-sysfs.c,提供一些相关函数如:devm_rtc_device_register                 /kernel/dirvers/rtc

l  rtc-dev.c  注册char驱动rtc,

l  rtc-sysfs.c                  sysfs相关文件

l  rtc-proc.c                   与/proc设备节点相关文件

l  systohc.c          Save NTPsynchronized time to the RTC

l  hctosys.c          linux开机启动系统时间设置

l  rtc-lib.c              时间转换相关函数实现

2.      驱动模型

说明:应用层可以通过三种方式访问RTC硬件,因为代码实现方式不同目前只有一种方式可写,其他方式只读。


1.      重要数据结构体

1.1  dts数据结构

myir_ricoboard.dts文件中加载rtc设备树

&rtc{

status = "okay";

};

am4372.dtsi文件中定义rtc数据结构

rtc: rtc@44e3e000 {

                       compatible= "ti,am4372-rtc","ti,da830-rtc";

                       reg = ;

                       interrupts= ;

                       ti,hwmods= "rtc";

                       clocks = ;

                       clock-names= "fck";

                       status ="disabled";

              };

1.2  rtc设备驱动加载相关数据结构

static struct platform_device_idomap_rtc_devtype[] = {

         {

                   .name       = DRIVER_NAME,

         },

         [OMAP_RTC_DATA_AM3352_IDX]= {

                   .name       = "am3352-rtc",

                   .driver_data= OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,

         },

         [OMAP_RTC_DATA_DA830_IDX]= {

                   .name       = "da830-rtc",

                   .driver_data= OMAP_RTC_HAS_KICKER,

         },

         {},

};

MODULE_DEVICE_TABLE(platform,omap_rtc_devtype);

static const struct of_device_idomap_rtc_of_match[] = {

         {        .compatible      = "ti,da830-rtc",

                   .data                  =&omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],

         },

         {        .compatible      = "ti,am3352-rtc",

                   .data                  = &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],

         },

         {},

};

MODULE_DEVICE_TABLE(of, omap_rtc_of_match);

1.3  rtc设备驱动与硬件层交互相关数据结构,

static struct rtc_class_ops omap_rtc_ops ={

         .read_time       = omap_rtc_read_time,

         .set_time          = omap_rtc_set_time,

         .read_alarm     = omap_rtc_read_alarm,

         .set_alarm       = omap_rtc_set_alarm,

         .alarm_irq_enable= omap_rtc_alarm_irq_enable,

};

1.4  rtc设备驱动与GPIO设置相关数据结构

#define OMAP_RTC_BASE                          0xfffb4800

/* OMAP_RTC_KICKER values */

#define     KICK0_VALUE                     0x83e70b13

#define     KICK1_VALUE                     0x95a4f1e0

1.5  rtc设备驱动与/dev设备节点交互相关数据结构

static const struct file_operationsrtc_dev_fops = {

         .owner               = THIS_MODULE,

         .llseek                = no_llseek,

         .read                  = rtc_dev_read,

         .poll           = rtc_dev_poll,

         .unlocked_ioctl         = rtc_dev_ioctl,

         .open                 = rtc_dev_open,

         .release   = rtc_dev_release,

         .fasync               = rtc_dev_fasync,

};

ATTRIBUTE_GROUPS(rtc);

1.6  rtc设备驱动与/proc设备节点交互相关数据结构

static const struct file_operationsrtc_proc_fops = {

         .open                 = rtc_proc_open,

         .read                  = seq_read,

         .llseek                = seq_lseek,

         .release   = rtc_proc_release,

};

1.7  rtc设备驱动与/sys/class/rtc相关数据结构

CONFIG_RTC_HCTOSYS_DEVICE="rtc0"

static struct attribute *rtc_attrs[] = {

         &dev_attr_name.attr,

         &dev_attr_date.attr,

         &dev_attr_time.attr,

         &dev_attr_since_epoch.attr,

         &dev_attr_max_user_freq.attr,

         &dev_attr_hctosys.attr,

         NULL,

};

1.8  时间转换相关结构体

static const unsigned charrtc_days_in_month[] = {

         31,28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31

};

static const unsigned shortrtc_ydays[2][13] = {

         /*Normal years */

         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },

         /*Leap years */

         {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }

};

三、RTC驱动重要函数介绍

1.      驱动加载函数

1.1  rtc_init函数

static int __init rtc_init(void)

{

         rtc_class= class_create(THIS_MODULE, "rtc");

         if(IS_ERR(rtc_class)) {

                   pr_err("couldn'tcreate class\n");

                   returnPTR_ERR(rtc_class);

         }

         rtc_class->pm= RTC_CLASS_DEV_PM_OPS;

         rtc_dev_init();

         rtc_sysfs_init(rtc_class);

         return0;

}

subsys_initcall(rtc_init);

1.2  omap_rtc_int

#if 0

module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);

#else

static int __init omap_rtc_driver_init(void)

{

     printk("=1=omap_rtc_driver_initmodule_init\n");

     returnplatform_driver_probe(&(omap_rtc_driver), omap_rtc_probe);   

}

module_init(omap_rtc_driver_init);

static void __exit omap_rtc_driver_exit(void)

{

     platform_driver_unregister(&(omap_rtc_driver));

}

module_exit(omap_rtc_driver_exit);

#endif

1.3  rtc_hctosys加载函数

static int __init rtc_hctosys(void)

{

         ………

}

late_initcall(rtc_hctosys);

voidrtc_proc_add_device(struct rtc_device *rtc)

{

if (is_rtc_hctosys(rtc))

           proc_create_data("driver/rtc",0, NULL, &rtc_proc_fops, rtc);

}

2.      Probe探针函数

static int __init omap_rtc_probe(structplatform_device *pdev)

{

         //of_match_device

         //omap_rtc_timer

         //omap_rtc_alarm

         //platform_get_device_id

         //devm_rtc_device_register

         //rtc gpio设置

}

devm_rtc_device_register –>rtc_device_register

{

rtc_dev_prepare;

device_register;

rtc_dev_add_device; //创建/dev/rtc*设备节点

rtc_sysfs_add_device; //创建/sys/class/rtc/rtc0设备节点

rtc_proc_add_device) //创建/proc/driver/rtc设备节点

}

3.      设备节点创建,操作函数

3.1  /dev/rtc*设备节点

3.1.1         创建函数

void rtc_dev_prepare(structrtc_device *rtc)

{

         if(!rtc_devt)

                   return;

         if(rtc->id >= RTC_DEV_MAX) {

                   dev_dbg(&rtc->dev,"%s: too many RTC devices\n", rtc->name);

                   return;

         }

         rtc->dev.devt= MKDEV(MAJOR(rtc_devt), rtc->id);

#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL

         INIT_WORK(&rtc->uie_task,rtc_uie_task);

         setup_timer(&rtc->uie_timer,rtc_uie_timer, (unsigned long)rtc);

#endif

       cdev_init(&rtc->char_dev,&rtc_dev_fops);//在这里静态初始化/dev设备节点,访问函数在rtc_dev_fops结构体中定义。

         rtc->char_dev.owner= rtc->owner;

}

void rtc_dev_add_device(struct rtc_device*rtc)

{

         if(cdev_add(&rtc->char_dev, rtc->dev.devt, 1))//将初始化的设备节点加载到系统中

                   dev_warn(&rtc->dev,"%s: failed to add char device %d:%d\n",

                            rtc->name,MAJOR(rtc_devt), rtc->id);

         else

                   dev_dbg(&rtc->dev,"%s: dev (%d:%d)\n", rtc->name,

                            MAJOR(rtc_devt),rtc->id);

}

3.1.2         open函数

static int rtc_dev_open(struct inode*inode, struct file *file)

{

         interr;

         structrtc_device *rtc = container_of(inode->i_cdev,

                                               structrtc_device, char_dev);

         conststruct rtc_class_ops *ops = rtc->ops;

         printk("=1=rtc_dev_open\n");

         if(test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))

                   return-EBUSY;

         printk("=2=rtc_dev_open\n");

         file->private_data= rtc;

         printk("=3=rtc_dev_open\n");

         err= ops->open ? ops->open(rtc->dev.parent) : 0;

         if(err == 0) {

                   spin_lock_irq(&rtc->irq_lock);

                   rtc->irq_data= 0;

                   spin_unlock_irq(&rtc->irq_lock);

                   return0;

         }

         printk("=4=rtc_dev_open\n");

         /*something has gone wrong */

         clear_bit_unlock(RTC_DEV_BUSY,&rtc->flags);

         returnerr;

}//open函数相应打开设备节点动作

}

3.1.3         rtc_dev_ioctl函数

static long rtc_dev_ioctl(struct file*file,

                   unsignedint cmd, unsigned long arg)

{//这里是此设备节点读写的实现,注意其会继续调用

        case RTC_RD_TIME:

                 mutex_unlock(&rtc->ops_lock);

                 err =rtc_read_time(rtc, &tm);

                 if (err ops_lock);

                 if(copy_from_user(&tm, uarg, sizeof(tm)))

                           return-EFAULT;

                 returnrtc_set_time(rtc, &tm);

…..

}

3.1.4         rtc_read_time函数

int rtc_read_time(struct rtc_device *rtc,struct rtc_time *tm)

{

         interr;

         err= mutex_lock_interruptible(&rtc->ops_lock);

         if(err)

                   returnerr;

         err= __rtc_read_time(rtc, tm);

         mutex_unlock(&rtc->ops_lock);

         returnerr;

}

EXPORT_SYMBOL_GPL(rtc_read_time);

3.1.5         rtc_set_time函数

int rtc_set_time(struct rtc_device *rtc,struct rtc_time *tm)

{

         interr;

         err= rtc_valid_tm(tm);

         if(err != 0)

                   returnerr;

         err= mutex_lock_interruptible(&rtc->ops_lock);

         if(err)

                   returnerr;

         if(!rtc->ops)

                   err= -ENODEV;

         elseif (rtc->ops->set_time)

                   err= rtc->ops->set_time(rtc->dev.parent, tm);

         elseif (rtc->ops->set_mmss) {

                   unsignedlong secs;

                   err= rtc_tm_to_time(tm, &secs);

                   if(err == 0)

                            err= rtc->ops->set_mmss(rtc->dev.parent, secs);

         }else

                   err= -EINVAL;

         mutex_unlock(&rtc->ops_lock);

         /*A timer might have just expired */

         schedule_work(&rtc->irqwork);

         returnerr;

}

EXPORT_SYMBOL_GPL(rtc_set_time);

3.1.6         omap_rtc_set_time函数

static int omap_rtc_set_time(struct device*dev, struct rtc_time *tm)

{

         if(tm2bcd(tm) tm_year,OMAP_RTC_YEARS_REG);

         rtc_write(tm->tm_mon,OMAP_RTC_MONTHS_REG);

         rtc_write(tm->tm_mday,OMAP_RTC_DAYS_REG);

         rtc_write(tm->tm_hour,OMAP_RTC_HOURS_REG);

         rtc_write(tm->tm_min,OMAP_RTC_MINUTES_REG);

         rtc_write(tm->tm_sec,OMAP_RTC_SECONDS_REG);

         local_irq_enable();

         return0;

}

3.1.7         omap_rtc_read_time函数

static int omap_rtc_read_time(struct device*dev, struct rtc_time *tm)

{

         /*we don't report wday/yday/isdst ... */

         local_irq_disable();

         rtc_wait_not_busy();

         tm->tm_sec= rtc_read(OMAP_RTC_SECONDS_REG);

         tm->tm_min= rtc_read(OMAP_RTC_MINUTES_REG);

         tm->tm_hour= rtc_read(OMAP_RTC_HOURS_REG);

         tm->tm_mday= rtc_read(OMAP_RTC_DAYS_REG);

         tm->tm_mon= rtc_read(OMAP_RTC_MONTHS_REG);

         tm->tm_year= rtc_read(OMAP_RTC_YEARS_REG);

         local_irq_enable();

         bcd2tm(tm);

         return0;

}

3.1.8         

        omap_rtc_set_time函数

3.2  /sys/class/rtc/rtc0设备节点

3.2.1         注册函数

void __init rtc_sysfs_init(struct class*rtc_class)

{

         printk("=1=rtc_sysfs_init\n");

         rtc_class->dev_groups= rtc_groups;//将与设备节点相关的操作初始化

}

上面的赋值需要下面的结构体和ATTRIBUTE_GROUPS宏线运行。

static struct attribute *rtc_attrs[] = {

         &dev_attr_name.attr,

         &dev_attr_date.attr,

         &dev_attr_time.attr,

         &dev_attr_since_epoch.attr,

         &dev_attr_max_user_freq.attr,

         &dev_attr_hctosys.attr,

         NULL,

};

ATTRIBUTE_GROUPS(rtc);//

void rtc_sysfs_add_device(struct rtc_device*rtc)

{

         interr;

         /*not all RTCs support both alarms and wakeup */

         if(!rtc_does_wakealarm(rtc))

                   return;

         err= device_create_file(&rtc->dev, &dev_attr_wakealarm);//设备节点真正创建

         if(err)

                   dev_err(rtc->dev.parent,

                            "failedto create alarm attribute, %d\n", err);

}

3.2.2         操作节点相关函数

static DEVICE_ATTR_RO(name);注意其是RO模式

static ssize_t

name_show(struct device *dev, structdevice_attribute *attr, char *buf)

{

         returnsprintf(buf, "%s\n", to_rtc_device(dev)->name);

}

static DEVICE_ATTR_RO(date);

static DEVICE_ATTR_RO(time);

static DEVICE_ATTR_RO(since_epoch);

static DEVICE_ATTR_RW(max_user_freq);

static DEVICE_ATTR_RO(hctosys);

ATTRIBUTE_GROUPS(rtc);

static DEVICE_ATTR(wakealarm, S_IRUGO |S_IWUSR,

                   rtc_sysfs_show_wakealarm,rtc_sysfs_set_wakealarm);

3.3  /proc/driver/rtc设备节点

3.3.1         设备节点创建

static const struct file_operationsrtc_proc_fops = {

         .open                 = rtc_proc_open,

         .read                  = seq_read,

         .llseek                = seq_lseek,

         .release   = rtc_proc_release,

};

void rtc_proc_add_device(struct rtc_device*rtc)

{

         printk("=1=rtc_proc_add_device\n");

         if(is_rtc_hctosys(rtc))

                   proc_create_data("driver/rtc",0, NULL, &rtc_proc_fops, rtc);

         printk("=2=rtc_proc_add_device\n");

}

3.3.2         Open函数

static int rtc_proc_open(struct inode*inode, struct file *file)

{

         intret;

         structrtc_device *rtc = PDE_DATA(inode);

         if(!try_module_get(THIS_MODULE))

                   return-ENODEV;

         ret= single_open(file, rtc_proc_show, rtc);

         if(ret)

                   module_put(THIS_MODULE);

         returnret;

}

3.3.3         rtc_proc_show函数实现。

static int rtc_proc_show(struct seq_file*seq, void *offset)

{

         interr;

         structrtc_device *rtc = seq->private;

         conststruct rtc_class_ops *ops = rtc->ops;

         structrtc_wkalrm alrm;

         structrtc_time tm;

         err= rtc_read_time(rtc, &tm);

         if(err == 0) {

                   seq_printf(seq,

                            "rtc_time\t:%02d:%02d:%02d\n"

                            "rtc_date\t:%04d-%02d-%02d\n",

                            tm.tm_hour,tm.tm_min, tm.tm_sec,

                            tm.tm_year+ 1900, tm.tm_mon + 1, tm.tm_mday);

         }

         err= rtc_read_alarm(rtc, &alrm);

         if(err == 0) {

                   seq_printf(seq,"alrm_time\t: ");

                   if((unsigned int)alrm.time.tm_hour uie_rtctimer.enabled)? "yes" : "no");

                   seq_printf(seq,"periodic IRQ enabled\t: %s\n",

                            (rtc->pie_enabled)? "yes" : "no");

                   seq_printf(seq,"periodic IRQ frequency\t: %d\n",

                            rtc->irq_freq);

                   seq_printf(seq,"max user IRQ frequency\t: %d\n",

                            rtc->max_user_freq);

         }

         seq_printf(seq,"24hr\t\t: yes\n");

         if(ops->proc)

                   ops->proc(rtc->dev.parent,seq);

         return0;

}

3.3.4         seq_read实现,与proc文件系统密切相关。

4.      GPIO相关函数

rtc_read rtc_write rtc_writel

5.      时间转换函数

跟01-01-1970 00:00:00转化秒数为time结构体时间,函数比较多就不一一列举。

Convert seconds since 01-01-1970 00:00:00 to Gregoriandate.

void rtc_time_to_tm(unsigned long time,struct rtc_time *tm)

{

         unsignedint month, year;

         intdays;

         days= time / 86400;

         time-= (unsigned int) days * 86400;

         /*day of the week, 1970-01-01 was a Thursday */

         tm->tm_wday= (days + 4) % 7;

         year= 1970 + days / 365;

         days-= (year - 1970) * 365

                   +LEAPS_THRU_END_OF(year - 1)

                   -LEAPS_THRU_END_OF(1970 - 1);

         if(days tm_year= year - 1900;

         tm->tm_yday= days + 1;

         for(month = 0; month tm_mon= month;

         tm->tm_mday= days + 1;

         tm->tm_hour= time / 3600;

         time-= tm->tm_hour * 3600;

         tm->tm_min= time / 60;

         tm->tm_sec= time - tm->tm_min * 60;

         tm->tm_isdst= 0;

}


四、用户层应用

1.      通过/proc文件系统访问rtc

1.1   源代码

直接通过cat命令访问设备节点cat /proc/driver/rtc

1.2   Kernel log和驱动响应

root@m437x-evm:~# cat /proc/driver/rtc

=1=rtc_proc_open

=2=rtc_proc_open

=3=rtc_proc_open

=4=rtc_proc_open

=1=rtc_read_time

=1=__rtc_read_time

=1=omap_rtc_read_time

=2=omap_rtc_read_time

=2=__rtc_read_time

=2=rtc_read_time

rtc_time        : 14:38:18

rtc_date        : 2016-11-09

alrm_time       : 00:00:00

alrm_date       : 2000-01-01

alarm_IRQ       : no

alrm_pending    : no

update IRQ enabled      :no

periodic IRQ enabled    : no

periodic IRQ frequency  : 1

max user IRQ frequency  : 64

24hr            : yes

2.      通过/sys文件系统访问rtc

直接使用cat对/sys/class/rtc/rtc0下面的节点进行访问,不过只能读而已。

root@m437x-evm:/sys/class/rtc/rtc0# catdate

=1=rtc_read_time

=1=__rtc_read_time

=1=omap_rtc_read_time

=2=omap_rtc_read_time

=2=__rtc_read_time

=2=rtc_read_time

2016-11-09

root@m437x-evm:/sys/class/rtc/rtc0# cattime

=1=rtc_read_time

=1=__rtc_read_time

=1=omap_rtc_read_time

=2=omap_rtc_read_time

=2=__rtc_read_time

=2=rtc_read_time

14:39:40

3.      通过/dev目录访问rtc

3.1   源代码

/********************************************************************

*               copyright(C) 2014 all rights reserved

*                          @file: rtc_test.c

*                 @Created: 2014-8-7 10:30

*                @Author: conway chen

*        @Description: read and write rtc time  

*         @modify Date: 2014-8-7 10:30

*********************************************************************/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

   

static const char default_rtc[] ="/dev/rtc0";

static char *program_name;

/**

*@brief: print help message

*/

static void help(void)

{      

         fprintf(stderr,

"\tUsage: %s [OPTION]...\n"

"\t-h,--help      help\n"

"\t-s,--set       set date/time given with you.\n\tinputformat:./rtc_test [hour] [minute] [second] [year] [month] [day]\n"

"\t-r,--show      read hardware clock and print result\n"

"\n", program_name);

}

/**

*@brief: read RTC date and time

*@Param: fd: the file descriptor of rtc device

*/

void rtc_read_time(int fd)

{

         intretval;

         structrtc_time rtc_tm;

         

         /*readthe RTC time/date*/

         retval= ioctl(fd, RTC_RD_TIME, &rtc_tm);

         if(retval == -1) {

                   perror("RTC_RD_TIMEioctl");

                   exit(errno);

         }

         fprintf(stderr,"\n\tCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n\n",

                   rtc_tm.tm_mday,rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,

                   rtc_tm.tm_hour,rtc_tm.tm_min, rtc_tm.tm_sec);

         

}

/**

*@brief: set rtc date and time  

*@Param: fd: the file descriptor of rtc device

*@Param: hour: the hour to set

*@Param: minute: the minute to set

*@Param: second: the hour to set

*@Param: year: the year to set

*@Param: month: the month to set

*@Param: day: the day to set

*/

void rtc_set_time(int fd, int hour, intminute, int second, int year, int month, int day)

{

         intretval;

         structrtc_time rtc_tm;

         

         rtc_tm.tm_mday= day;

         rtc_tm.tm_mon= month - 1;

         rtc_tm.tm_year= year - 1900;

         rtc_tm.tm_hour= hour;

         rtc_tm.tm_min= minute;

         rtc_tm.tm_wday= rtc_tm.tm_yday = rtc_tm.tm_isdst = 0;

         rtc_tm.tm_sec= second;

         /*setthe RTC time/date*/

         retval= ioctl(fd, RTC_SET_TIME, &rtc_tm);

         if(retval == -1) {

                   perror("RTC_SET_TIMEioctl");

                   exit(errno);

         }        

         

         fprintf(stderr,"\n\t\tdate/time is updated to: %d-%d-%d, %02d:%02d:%02d.\n\n",

                   rtc_tm.tm_mday,rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,

                   rtc_tm.tm_hour,rtc_tm.tm_min, rtc_tm.tm_sec);

}

/**

*@brief: main function  

*@Param: argc: number of parameters

*@Param: argv: parameters list

*/

int main(int argc, char *argv[])

{

         intfd, retval, c;

         intset_flag = 0, read_flag = 0;

         structrtc_time rtc_tm;

         constchar *rtc = default_rtc;

         

         structoption long_option[] =

    {

             {"help", 0, NULL, 'h'},        

       {"set", 1, NULL, 's'},

       {"show", 0, NULL, 'r'},

       {NULL, 0, NULL, 0},

   };

   

   program_name = argv[0];            

         

   while (1) {

             if ((c = getopt_long(argc, argv,"hs:r", long_option, NULL)) < 0)

                       break;

             switch (c) {

                   case'h':

                                     help();

                                     break;               

                   case's':

                                     if(argc < 8) {

                                     fprintf(stderr,"\n\t\ttime format error!\n\n");

                                     exit(errno);      

                                     }        

                                     set_flag= 1;

                                     break;

                   case'r':

                                     read_flag= 1;

                                     break;

                   case'?':

                                     help();

                                     break;

                   default:

                                     abort();

             }

    }

   

   /* open rtc device */

   fd = open(rtc, O_RDWR);

         if(fd ==  -1) {

                   perror(rtc);

                   exit(errno);

         }

         

         if(argc == 1) {

                   rtc_read_time(fd);  

         }

   

   if (set_flag)

                   rtc_set_time(fd,atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]), atoi(argv[6]),atoi(argv[7]));

         if(read_flag)

                   rtc_read_time(fd);

   

   close(fd);

         return0;

}


3.2   驱动响应代码和Kernel log





4.      linux系统命令hwclock

hwclock -w//将系统时钟写入硬件时钟


hwclock -s//将硬件时钟写入系统时钟


hwclock –r//显示硬件时钟

root@m437x-evm:/opt# hwclock -r

=1=rtc_dev_open

=2=rtc_dev_open

=3=rtc_dev_open

=RTC_RD_TIME=rtc_dev_ioctl

=1=rtc_read_time

=1=__rtc_read_time

=1=omap_rtc_read_time

=2=omap_rtc_read_time

=2=__rtc_read_time

=2=rtc_read_time

Sat Nov 19 11:15:12 2011  0.000000 seconds

5.      linux系统命令date

root@m437x-evm:/opt# date

Wed Nov 9 14:43:25 UTC 2016

知识点总结:

1.RTC相关概念,驱动代码简单分析;

2.linux设置,读取RTC时钟的方式和大概流程;

3.proc和alarm相关知识后面有时间在详细总结。


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top