1。我们要实现通过GPIO读写 DS1302的寄存器数据;
2。首先我们需要了解下DS1302的工作方式,它提供SCL、DATA、RST三个信号,然后可以参考其时序图进行数据的读写;
3。我们现在就是要通过GPIO来模拟整个读写的时序;
4。下面的代码是linux2.4下的,当然只能适合我的CPU,应该不同的CPU的GPIO寄存器地址都不一样,如果你使用需要修改;
头文件主要定义了DS1302的操作地址、及tm时间结构等;
/* $Id: rtc.h,v 1.3 2001/03/21 09:56:31 magnusmn Exp $ */
#ifndef DS1302_H
#define DS1302_H
#include
#include
/* Dallas DS1302 clock/calendar register numbers */
/*
#define RTC_SECONDS 0
#define RTC_MINUTES 1
#define RTC_HOURS 2
#define RTC_DAY_OF_MONTH 3
#define RTC_MONTH 4
#define RTC_WEEKDAY 5
#define RTC_YEAR 6
#define RTC_CONTROL 7
*/
#define RTC_SECONDS 0x80
#define RTC_MINUTES 0x82
#define RTC_HOURS 0x84
#define RTC_DAY_OF_MONTH 0x86
#define RTC_MONTH 0x88
#define RTC_WEEKDAY 0x8a
#define RTC_YEAR 0x8c
#define RTC_CONTROL 0x8e
#define RTC_TRICKLECHARGER 0x90
/* Bits in CONTROL register */
#define RTC_CONTROL_WRITEPROTECT 0x80
//#define RTC_TRICKLECHARGER 8
/* Bits in TRICKLECHARGER register TCS TCS TCS TCS DS DS RS RS */
#define RTC_TCR_PATTERN 0xA0 /* 1010xxxx */
#define RTC_TCR_1DIOD 0x04 /* xxxx01xx */
#define RTC_TCR_2DIOD 0x08 /* xxxx10xx */
#define RTC_TCR_DISABLED 0x00 /* xxxxxx00 Disabled */
#define RTC_TCR_2KOHM 0x01 /* xxxxxx01 2KOhm */
#define RTC_TCR_4KOHM 0x02 /* xxxxxx10 4kOhm */
#define RTC_TCR_8KOHM 0x03 /* xxxxxx11 8kOhm */
#ifdef CONFIG_ETRAX_DS1302
#define CMOS_READ(x) ds1302_readreg(x)
#define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
#define RTC_INIT() ds1302_init()
#else
/* no RTC configured so we shouldn't try to access any */
#define CMOS_READ(x) 42
#define CMOS_WRITE(x,y)
#define RTC_INIT() (-1)
#endif
/* conversions to and from the stupid RTC internal format */
#define BCD_TO_BIN(x) x = (((x & 0xf0) >> 3) * 5 + (x & 0xf))
#define BIN_TO_BCD(x) x = (x % 10) | ((x / 10) << 4)
/*
* The struct used to pass data via the following ioctl. Similar to the
* struct tm in , but it needs to be here so that the kernel
* source is self contained, allowing cross-compiles, etc. etc.
*/
struct rtc_time {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
#define RTC_MAJOR_NR 230
/*
* ioctl calls that are permitted to the /dev/rtc interface
*/
#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time) /* Read RTC time */
#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
#define RTC_SET_CHARGE _IOW('p', 0x0b, int) /* Set CHARGE mode */
//#define RTC_RD_TIME 66
//#define RTC_SET_TIME 77
//#define RTC_SET_CHARGE 88
#endif
实现文件
/*!***************************************************************************
*!
*! FILE NAME : ds1302.c
*!
*! DESCRIPTION: Implements an interface for the DS1302 RTC through Etrax I/O
*!
*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init, get_rtc_status
*! ---------------------------------------------------------------------------
*!
*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
*!
*! $Id: ds1302.c,v 1.11 2001/06/14 12:35:52 jonashg Exp $
*!
*!***************************************************************************/
/*
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include */
#include
#include
//#include
#include
#include
#include
#include
#include
#include
//#include
//#include
#include "ds1302n.h"
static int init_module(void);
static void cleanup_module(void);
static int ds1302_open(struct inode*, struct file *);
static int ds1302_close(struct inode*, struct file *);
static int rtc_ioctl(struct inode*inode,struct file *flip,unsigned int cmd,unsigned long arg);
static void ds1302_release(struct inode*inode, struct file *filp);
#define GPIO_MODE_OUTOFF 0x00
#define GPIO_MODE_INOFF 0x04
#define GPIO_MODE_DIROFF 0x08
#define GPIO_MODE_PULLENOFF 0x18
#define GPIO_MODE_PULLTYOFF 0x1C
#define DS1302_RST 0x0001
#define DS1302_SCL 0x0002
#define DS1302_SDA 0x0004
#define INN 0
#define OUTT 1
//#define RTC_MAJOR_NR 121 /* local major, change later */
static const char ds1302_name[] = "ds1302";
/* The DS1302 might be connected to different bits on different products.
* It has three signals - SDA, SCL and RST. RST and SCL are always outputs,
* but SDA can have a selected direction.
* For now, only PORT_PB is hardcoded.
*/
/* The RST bit may be on either the Generic Port or Port PB. */
/*
#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
#define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
#define TK_RST_DIR(x)
#else
//#define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
//#define TK_RST_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
#define TK_RST_OUT(x) write_gpio_bit(GPIO_MODE_OUT | DS1302_RST,x)
#define TK_RST_DIR(x)
#endif
//#define TK_SDA_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SDABIT, x)
#define TK_SDA_OUT(x) write_gpio_bit(GPIO_MODE_OUT | DS1302_SDA,x)
//#define TK_SCL_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SCLBIT, x)
#define TK_SCL_OUT(x) write_gpio_bit(GPIO_MODE_OUT | DS1302_SCL,x)
//#define TK_SDA_IN() ((*R_PORT_PB_READ >> CONFIG_ETRAX_DS1302_SDABIT) & 1)
#define TK_SDA_IN() read_gpio_bit(DS1302_SDA)
//#define TK_SDA_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_SDABIT, x)
//#define TK_SDA_DIR(x) (if(x==1) set_gpio_ctrl(GPIO_MODE_OUT | DS1302_SDA); else set_gpio_ctrl(GPIO_MODE_IN | DS1302_SDA); )
#define TK_SDA_DIR(x) set_gpio_ctrl(x | DS1302_SDA)
//#define TK_SCL_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_SCLBIT, x)
#define TK_SCL_DIR(x)*/
/* 1 is out, 0 is in */
void TK_SDA_OUT(char x)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_OUTOFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_OUTOFF) = (tmp & ~(1< return ((*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_INOFF)>>DS1302_SDA)&1) ;
}
void TK_SCL_OUT(char x)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_OUTOFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_OUTOFF) = ((tmp & ~(1< int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_OUTOFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_OUTOFF) = ((tmp & ~(1< if(dir==1)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF) = (tmp | 1< }
else if(dir==0)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF) = (tmp & ~(1< }
else;
}
void TK_SCL_DIR(char dir)
{
if(dir==1)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF) = (tmp | 1< }
else if(dir==0)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF) = (tmp & ~(1< }
else;
}
void TK_RST_DIR(char dir)
{
if(dir==1)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF) = (tmp | 1< }
else if(dir==0)
{
int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_DIROFF) = (tmp & ~(1< }
else;
}
/* Set the pin enable pulled. */
static void setpullenable(char x, char value)
{
int tmp;
tmp = *(volatile int *)(CPE_GPIO_VA_BASE + GPIO_MODE_PULLENOFF);
*(volatile int *)(CPE_GPIO_VA_BASE + GPIO_MODE_PULLENOFF) = ((tmp & ~(1< int tmp;
tmp = *(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_PULLTYOFF);
*(volatile int*)(CPE_GPIO_VA_BASE + GPIO_MODE_PULLTYOFF) = ((tmp & ~(1< volatile int loops;
for(loops = usecs * 12; loops > 0; loops--)
/* nothing */;
}
/* Send 8 bits. */
static void
out_byte(unsigned char x)
{
int i;
//TK_SDA_DIR(1);
TK_SDA_DIR(OUTT);
for (i = 8; i--;) {
/* The chip latches incoming bits on the rising edge of SCL. */
TK_SCL_OUT(0);
TK_SDA_OUT(x & 1);
tempudelay(1);
TK_SCL_OUT(1);
tempudelay(1);
x >>= 1;
}
//TK_SDA_DIR(0);
TK_SDA_DIR(INN);
}
static unsigned char
in_byte(void)
{
unsigned char x = 0;
int i;
/* Read byte. Bits come LSB first, on the falling edge of SCL.
* Assume SDA is in input direction already.
*/
//TK_SDA_DIR(0);
TK_SDA_DIR(INN);
for (i = 8; i--;) {
TK_SCL_OUT(0);
tempudelay(1);
x >>= 1;
x |= (TK_SDA_IN() << 7);
TK_SCL_OUT(1);
tempudelay(1);
}
return x;
}
/* Prepares for a transaction by de-activating RST (active-low). */
static void
start(void)
{
TK_SCL_OUT(0);
tempudelay(1);
TK_RST_OUT(0);
tempudelay(5);
TK_RST_OUT(1);
}
/* Ends a transaction by taking RST active again. */
static void
stop(void)
{
tempudelay(2);
TK_RST_OUT(0);
}
/* Enable writing. */
static void
ds1302_wenable(void)
{
start();
out_byte(0x8e); /* Write control register */
out_byte(0x00); /* Disable write protect bit 7 = 0 */
stop();
}
static void
ds1302_osc_enable(void)
{
char tmp;
start();
out_byte(0x81);
tmp=in_byte();
stop();
if((tmp&0x80)==0x00);
else
{
start();
out_byte(0x80);
out_byte(0x00);
stop();
}
}
/* Disable writing. */
static void
ds1302_wdisable(void)
{
start();
out_byte(0x8e); /* Write control register */
out_byte(0x80); /* Disable write protect bit 7 = 0 */
stop();
}
/* Probe for the chip by writing something to its RAM and try reading it back. */
#define MAGIC_PATTERN 0x42
static int
ds1302_probe(void)
{
int retval, res;
TK_RST_DIR(1);
TK_SCL_DIR(1);
//TK_SDA_DIR(0);
TK_SDA_DIR(INN);
ds1302_osc_enable();
ds1302_writereg(RTC_TRICKLECHARGER, 0x00);//disable the trickle charger
/* Try to talk to timekeeper. */
ds1302_wenable();
start();
out_byte(0xc0); /* write RAM byte 0 */
out_byte(MAGIC_PATTERN); /* write something magic */
start();
out_byte(0xc1); /* read RAM byte 0 */
if((res = in_byte()) == MAGIC_PATTERN) {
char buf[100];
stop();
ds1302_wdisable();
printk("%s: RTC found.\n", ds1302_name);
/*
printk("%s: SDA, SCL, RST on PB%i, PB%i, %s%i\n",
ds1302_name,
CONFIG_ETRAX_DS1302_SDABIT,
CONFIG_ETRAX_DS1302_SCLBIT,
#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
"GENIO",
#else
"PB",
#endif
CONFIG_ETRAX_DS1302_RSTBIT);*/
get_rtc_status(buf);
printk(buf);
retval = 1;
} else {
stop();
printk("%s: RTC not found.\n", ds1302_name);
retval = 0;
}
return retval;
}
/* Read a byte from the selected register in the DS1302. */
static unsigned char
ds1302_readreg(int reg)
{
unsigned char x;
start();
//out_byte(0x81 | (reg << 1)); /* read register */
out_byte(reg|0x01);
x = in_byte();
stop();
return x;
}
/* Write a byte to the selected register. */
static void
ds1302_writereg( unsigned char val,int reg)
{
ds1302_wenable();
start();
//out_byte(0x80 | (reg << 1)); /* write register */
out_byte(reg&0xfe);
out_byte(val);
stop();
ds1302_wdisable();
}
static void
get_rtc_time(struct rtc_time *rtc_tm)
{
unsigned long flags;
save_flags(flags);
cli();
/*
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
*/
rtc_tm->tm_sec= ds1302_readreg(RTC_SECONDS);
rtc_tm->tm_min = ds1302_readreg(RTC_MINUTES);
rtc_tm->tm_hour = ds1302_readreg(RTC_HOURS);
rtc_tm->tm_mday = ds1302_readreg(RTC_DAY_OF_MONTH);
rtc_tm->tm_mon = ds1302_readreg(RTC_MONTH);
rtc_tm->tm_year = ds1302_readreg(RTC_YEAR);
rtc_tm->tm_wday = ds1302_readreg(RTC_WEEKDAY);
restore_flags(flags);
BCD_TO_BIN(rtc_tm->tm_sec);
BCD_TO_BIN(rtc_tm->tm_min);
BCD_TO_BIN(rtc_tm->tm_hour);
BCD_TO_BIN(rtc_tm->tm_mday);
BCD_TO_BIN(rtc_tm->tm_mon);
BCD_TO_BIN(rtc_tm->tm_year);
BCD_TO_BIN(rtc_tm->tm_wday);
/*
* Account for differences between how the RTC uses the values
* and how they are defined in a struct rtc_time;
*/
rtc_tm->tm_wday-=1;
if (rtc_tm->tm_year <= 69)
rtc_tm->tm_year += 100;
rtc_tm->tm_mon--;
}
static unsigned char days_in_mo[] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */
static int
rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned long flags;
switch(cmd) {
case RTC_RD_TIME: /* read the time/date from RTC */
{
struct rtc_time rtc_tm;
get_rtc_time(&rtc_tm);
if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
return -EFAULT;
return 0;
}
case RTC_SET_TIME: /* set the RTC */
{
struct rtc_time rtc_tm;
unsigned char mon, day, hrs, min, sec, leap_yr,wday;
unsigned char save_control, save_freq_select;
unsigned int yrs;
if (!capable(CAP_SYS_TIME))
{
printk("capable failed.\n");
return -EPERM;
}
if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
{
printk("copy_from_user failed.\n");
return -EFAULT;
}
yrs = rtc_tm.tm_year + 1900;
mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
day = rtc_tm.tm_mday;
hrs = rtc_tm.tm_hour;
min = rtc_tm.tm_min;
sec = rtc_tm.tm_sec;
wday= rtc_tm.tm_wday+1;
if ((yrs < 1970) || (yrs > 2069))
return -EINVAL;
leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
if ((mon > 12) || (day == 0))
return -EINVAL;
if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
return -EINVAL;
if ((hrs >= 24) || (min >= 60) || (sec >= 60))
return -EINVAL;
if(wday>7)
return -EINVAL;
if (yrs >= 2000)
yrs -= 2000; /* RTC (0, 1, ... 69) */
else
yrs -= 1900; /* RTC (70, 71, ... 99) */
BIN_TO_BCD(sec);
BIN_TO_BCD(min);
BIN_TO_BCD(hrs);
BIN_TO_BCD(day);
BIN_TO_BCD(mon);
BIN_TO_BCD(yrs);
BIN_TO_BCD(wday);
save_flags(flags);
cli();
/*
CMOS_WRITE(yrs, RTC_YEAR);
CMOS_WRITE(mon, RTC_MONTH);
CMOS_WRITE(day, RTC_DAY_OF_MONTH);
CMOS_WRITE(hrs, RTC_HOURS);
CMOS_WRITE(min, RTC_MINUTES);
CMOS_WRITE(sec, RTC_SECONDS);
*/
ds1302_writereg(yrs, RTC_YEAR);
ds1302_writereg(mon, RTC_MONTH);
ds1302_writereg(day, RTC_DAY_OF_MONTH);
ds1302_writereg(hrs, RTC_HOURS);
ds1302_writereg(min, RTC_MINUTES);
ds1302_writereg(sec, RTC_SECONDS);
ds1302_writereg(wday, RTC_WEEKDAY);
restore_flags(flags);
/* Notice that at this point, the RTC is updated but
* the kernel is still running with the old time.
* You need to set that separately with settimeofday
* or adjtimex.
*/
return 0;
}
case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */
{
int tcs_val;
unsigned char save_control, save_freq_select;
if (!capable(CAP_SYS_TIME))
return -EPERM;
if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
return -EFAULT;
//tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
tcs_val &= 0x0F; // disable the trickle charger
ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
return 0;
}
default:
return -ENOIOCTLCMD;
}
}
static int
get_rtc_status(char *buf)
{
char *p;
struct rtc_time tm;
p = buf;
get_rtc_time(&tm);
/*
* There is no way to tell if the luser has the RTC set for local
* time or for Universal Standard Time (GMT). Probably local though.
*/
p += sprintf(p,
"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);
return p - buf;
}
/* The various file operations we support. */
static struct file_operations rtc_fops = {
owner: THIS_MODULE,
ioctl: rtc_ioctl,
open: ds1302_open,
release: ds1302_release,
};
/* Just probe for the RTC and register the device to handle the ioctl needed. */
static int
init_module(void)
{
int ret;
setpullenable(DS1302_SCL, 1);
setpullenable(DS1302_RST, 1);
setpulltype(DS1302_SCL, 1);
setpulltype(DS1302_RST, 1);
if (!ds1302_probe()) {
//#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
/*
* The only way to set g27 to output is to enable ATA.
*
* Make sure that R_GEN_CONFIG is setup correct.
*/
// genconfig_shadow = ((genconfig_shadow &
// ~IO_MASK(R_GEN_CONFIG, ata))
// |
//(IO_STATE(R_GEN_CONFIG, ata, select)));
// *R_GEN_CONFIG = genconfig_shadow;
//if (!ds1302_probe())
//return -1;
//#else
printk("probe fail....\n");
return -1;
//#endif
}
if (ret=register_chrdev(RTC_MAJOR_NR, ds1302_name, &rtc_fops)) {
printk(KERN_INFO "%s: unable to get major %d for rtc\n",
ds1302_name, RTC_MAJOR_NR);
return -1;
}
return 0;
}
static void cleanup_module(void)
{
unregister_chrdev(RTC_MAJOR_NR, ds1302_name);
}
static void ds1302_release(struct inode*inode, struct file *filp)
{
return;
}
static int ds1302_open(struct inode*inode, struct file *filp)
{
return 0;
}
static int ds1302_close(struct inode*inode, struct file *filp)
{
return 0;
}
//module_init(ds1302_init); //用户加载该驱动时执行insmod gpio_driv.o就会自动调用gpio_init函数,它是驱动
//的入口点,相当于应用程序的main函数。
//module_exit(ds1302_release); //用户卸载该驱动rmmod gpio_driv时执行
驱动编译完成后,我们接好硬件就可以测试下
测试代码如下:
#include "ds1302n.h"
#include
#include
#include
#include
#define DEVICE_FILE "/dev/ds1302"
int main(int argc, char** argv)
{
int fds1302, ret;
struct rtc_time rtc_tm;
fds1302 = open(DEVICE_FILE, 0);
if(fds1302 < 0)
{
printf("Can't Open device file: %s\n", DEVICE_FILE);
exit(-1);
}
ret = ioctl(fds1302, RTC_RD_TIME, &rtc_tm);
if(ret == 0)
{
printf("Time: %04d-%02d-%02d %02d:%02d:%02d\n", rtc_tm.tm_year+1900, rtc_tm.tm_mon+1,
rtc_tm.tm_mday, rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
}
memset(&rtc_tm, 0, sizeof(struct rtc_time));
rtc_tm.tm_year = 2013 - 1900;
rtc_tm.tm_mon = 5 - 1;
rtc_tm.tm_mday = 10;
rtc_tm.tm_hour = 14;
rtc_tm.tm_min = 18;
rtc_tm.tm_sec = 59;
ret = ioctl(fds1302, RTC_SET_TIME, &rtc_tm);
if(ret != 0)
printf("ioctl failed.\n");
return 0;
}