April 18, 2024, 03:36:46 PM

MOD-RTC - Unable to set time

Started by rhiakath, March 27, 2013, 02:40:29 PM

Previous topic - Next topic

rhiakath

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