Hi there. I've written a small piece of C code to get and set the time on the RTC UEXT.
The read works very well, and i can see it increment the seconds. Unfortunately, I seem to be unable to set the time. There is no error writing to the register itself, but if i read it afterward, it has nothing to do with what i wrote.
Also, the values change everytime i write, they don't get completely discarded, so i must be hitting something.
I've tried on an A13, and a iMX233. The results are the same.
this is my code, currently for the I2C bus on the iMX233. On the A13, it should be bus 2.
#include "RTC.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#define I2C_Filename "/dev/i2c-0"
#define I2C_RTCAddress 0x51
char *Weekdays[7]= {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
int ReadSystemTime ( uint8_t *Out_Day, uint8_t *Out_Month, uint8_t *Out_Year, uint8_t *Out_Weekday, uint8_t *Out_Hour, uint8_t *Out_Minute, uint8_t *Out_Second )
{
struct timeval Now;
struct tm *tm;
printf ( "Reading system time\n" );
gettimeofday ( &Now, NULL );
tm = localtime ( &Now.tv_sec );
*Out_Second = tm->tm_sec;
*Out_Minute = tm->tm_min;
*Out_Hour = tm->tm_hour;
*Out_Day = tm->tm_mday;
*Out_Month = tm->tm_mon + 1;
*Out_Year = tm->tm_year % 100;
*Out_Weekday = tm->tm_wday;
printf ( "System time is %d:%d:%d %d/%d/%d ( %s )\n", *Out_Hour, *Out_Minute, *Out_Second, *Out_Day, *Out_Month, *Out_Year, Weekdays[*Out_Weekday] );
return 0;
}
int WriteSystemTime ( uint8_t In_Day, uint8_t In_Month, uint8_t In_Year, uint8_t In_Weekday, uint8_t In_Hour, uint8_t In_Minute, uint8_t In_Second )
{
printf ( "Setting system time to %d:%d:%d %d/%d/%d ( %s )\n", In_Hour, In_Minute, In_Second, In_Day, In_Month, In_Year, Weekdays[In_Weekday] );
struct tm time1;
memset ( &time1, 0, sizeof ( time1 ) );
time1.tm_sec = In_Second;
time1.tm_min = In_Minute;
time1.tm_hour = In_Hour;
time1.tm_mday = In_Day;
time1.tm_mon = In_Month - 1;
time1.tm_year = In_Year + 100;
time_t time2 = mktime ( &time1 );
stime ( &time2 );
return 0;
}
int ReadRTC ( uint8_t *Out_Day, uint8_t *Out_Month, uint8_t *Out_Year, uint8_t *Out_Weekday, uint8_t *Out_Hour, uint8_t *Out_Minute, uint8_t *Out_Second )
{
int FileDescriptor;
int Result;
printf ( "Reading time from RTC\n" );
if ( ( FileDescriptor = open ( I2C_Filename, O_RDWR ) ) < 0 )
{
printf ( "%s - Unable to open filename %s. \"%s\"\n", __FUNCTION__, I2C_Filename, strerror ( errno ) );
return -1;
}
if ( ioctl ( FileDescriptor, I2C_SLAVE, I2C_RTCAddress ) < 0 )
{
printf ( "%s - Unable to do ioctl. \"%s\"\n", __FUNCTION__, strerror ( errno ) );
close ( FileDescriptor );
return -1;
}
uint8_t buffer[1];
buffer[0] = 0x02; // Data address dos segundos
Result = write ( FileDescriptor, buffer, sizeof ( buffer ) );
if ( Result != sizeof ( buffer ) )
{
printf ( "%s - Unable to write to i2c buffer. \"%s\"\n", __FUNCTION__, strerror ( errno ) );
close ( FileDescriptor );
return -1;
}
uint8_t Answer[7];
Result = read ( FileDescriptor, Answer, sizeof ( Answer ) );
if ( Result != sizeof ( Answer ) )
{
printf ( "%s - Unable to read from i2c buffer. \"%s\"\n", __FUNCTION__, strerror ( errno ) );
close ( FileDescriptor );
return -1;
}
for ( Result = 0; Result < sizeof ( Answer ); ++Result )
printf ( "%02X ", Answer[Result] );
printf ( "\n" );
*Out_Second = BCDToDecimal ( Answer[0] & 0x7F );
*Out_Minute = BCDToDecimal ( Answer[0] & 0x7F );
*Out_Hour = BCDToDecimal ( Answer[0] & 0x3F );
*Out_Day = BCDToDecimal ( Answer[0] & 0x03F );
*Out_Weekday = BCDToDecimal ( Answer[0] & 0x07 );
*Out_Month = BCDToDecimal ( Answer[0] & 0x1F );
*Out_Year = BCDToDecimal ( Answer[0] & 0xFF );
printf ( "RTC time is %d:%d:%d %d/%d/%d ( %s )\n", *Out_Hour, *Out_Minute, *Out_Second, *Out_Day, *Out_Month, *Out_Year, Weekdays[*Out_Weekday] );
close ( FileDescriptor );
return 0;
}
int WriteRTC ( uint8_t In_Day, uint8_t In_Month, uint8_t In_Year, uint8_t In_Weekday, uint8_t In_Hour, uint8_t In_Minute, uint8_t In_Second )
{
int FileDescriptor;
int Result;
printf ( "Setting RTC time to %d:%d:%d %d/%d/%d ( %s )\n", In_Hour, In_Minute, In_Second, In_Day, In_Month, In_Year, Weekdays[In_Weekday] );
if ( ( FileDescriptor = open ( I2C_Filename, O_RDWR ) ) < 0 )
{
printf ( "%s - Unable to open filename %s. \"%s\"\n", __FUNCTION__, I2C_Filename, strerror ( errno ) );
return -1;
}
if ( ioctl ( FileDescriptor, I2C_SLAVE, I2C_RTCAddress ) < 0 )
{
printf ( "%s - Unable to do ioctl. \"%s\"\n", __FUNCTION__, strerror ( errno ) );
close ( FileDescriptor );
return -1;
}
uint8_t buffer[1];
buffer[0] = 0x02; // Data address dos segundos
uint8_t NewTime[7];
NewTime[0] = DecimalToBCD ( In_Second );
NewTime[1] = DecimalToBCD ( In_Minute );
NewTime[2] = DecimalToBCD ( In_Hour );
NewTime[3] = DecimalToBCD ( In_Day );
NewTime[4] = DecimalToBCD ( In_Weekday );
NewTime[5] = DecimalToBCD ( In_Month );
NewTime[6] = DecimalToBCD ( In_Year );
uint8_t FullBuffer[8];
FullBuffer[0] = 0x02;
memcpy ( FullBuffer + 1, &NewTime, sizeof ( NewTime ) );
usleep ( 1000 );
Result = write ( FileDescriptor, buffer, sizeof ( buffer ) );
if ( Result != sizeof ( buffer ) )
/*Result = write ( FileDescriptor, FullBuffer, sizeof ( FullBuffer ) );
if ( Result != sizeof ( FullBuffer ) )*/
{
printf ( "%s - Unable to write to i2c buffer. \"%s\"\n", __FUNCTION__, strerror ( errno ) );
close ( FileDescriptor );
return -1;
}
for ( Result = 0; Result < sizeof ( NewTime ); ++Result )
printf ( "%02X ", NewTime[Result] );
printf ( "\n" );
Result = write ( FileDescriptor, NewTime, sizeof ( NewTime ) );
if ( Result != sizeof ( NewTime ) )
{
printf ( "%s - Unable to write to i2c buffer. \"%s\"\n", __FUNCTION__, strerror ( errno ) );
close ( FileDescriptor );
return -1;
}
close ( FileDescriptor );
return 0;
}
unsigned BCDToDecimal ( unsigned In_BCD )
{
unsigned cont = 0;
unsigned Result = 0;
for ( cont = 0; cont < sizeof ( In_BCD ); ++cont )
{
Result += ( In_BCD & 0x0F ) * pow ( 10, cont );
In_BCD >>= 4;
}
return Result;
}
unsigned DecimalToBCD ( unsigned In_Decimal )
{
unsigned cont = 0;
unsigned Result = 0;
for ( cont = 0; cont < sizeof ( In_Decimal ); ++cont )
{
Result += In_Decimal % 10 * pow ( 0x10, cont );
In_Decimal /= 10;
}
return Result;
}
int main ( int argc, char *argv[] )
{
uint8_t Hours, Minutes, Seconds, Day, Month, Year, Weekday;
ReadRTC ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
ReadSystemTime ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
if ( argc != 2 )
return -1;
switch ( argv[1][0] )
{
case 'l':
{
printf ( "Setting system time from RTC\n" );
ReadRTC ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
WriteSystemTime ( Day, Month, Year, Weekday, Hours, Minutes, Seconds );
break;
}
case 's':
{
printf ( "Saving system time to RTC\n" );
ReadSystemTime ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
WriteRTC ( Day, Month, Year, Weekday, Hours, Minutes, Seconds );
break;
}
case 'b':
{
printf ( "Testing BCD conversion\n" );
unsigned cont;
printf ( "BCDToDecimal\n" );
for ( cont = 0; cont < 0xFF; ++cont )
{
if ( ( cont & 0x0F ) >= 0x0A ) continue;
if ( ( ( cont >> 4 ) & 0x0F ) >= 0x0A ) continue;
printf ( "BCD - %02X DEC - %d\n", cont, BCDToDecimal ( cont ) );
}
printf ( "DecimalToBCD\n" );
for ( cont = 0; cont < 0xFF; ++cont )
{
printf ( "BCD - %02X DEC - %d\n", DecimalToBCD ( cont ), cont );
}
break;
}
case 't':
{
while ( 1 )
{
printf ( "Saving system time to RTC\n" );
ReadSystemTime ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
WriteRTC ( Day, Month, Year, Weekday, Hours, Minutes, Seconds );
sleep ( 1 );
ReadRTC ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
printf ( "\n\n\n" );
}
break;
}
}
sleep ( 1 );
ReadRTC ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
ReadSystemTime ( &Day, &Month, &Year, &Weekday, &Hours, &Minutes, &Seconds );
return 0;
}
A sample run outputs this:
Reading time from RTC
27 27 27 27 27 32 27
RTC time is 27:27:27 27/12/27 ( (null) )
Reading system time
System time is 12:38:34 27/3/13 ( Wednesday )
Saving system time to RTC
Reading system time
System time is 12:38:34 27/3/13 ( Wednesday )
Setting RTC time to 12:38:34 27/3/13 ( Wednesday )
34 38 12 27 03 03 13
Reading time from RTC
27 27 38 12 27 23 03
RTC time is 38:27:27 12/3/3 ( (null) )
Saving system time to RTC
Reading system time
System time is 12:38:35 27/3/13 ( Wednesday )
Setting RTC time to 12:38:35 27/3/13 ( Wednesday )
35 38 12 27 03 03 13
Reading time from RTC
27 27 38 38 22 27 03
RTC time is 38:27:27 38/7/3 ( Tuesday )
Saving system time to RTC
Reading system time
System time is 12:38:36 27/3/13 ( Wednesday )
Setting RTC time to 12:38:36 27/3/13 ( Wednesday )
36 38 12 27 03 03 13
Reading time from RTC
27 27 38 38 20 32 27
RTC time is 38:27:27 38/12/27 ( Sunday )
What am I doing wrong?
Thank you