none
How to read RTC registers via I2C?? RRS feed

  • Question

  • Hello Friends,

    I am working on I2C-RTC application. I have successfully written I2C application up to setting the slave(RTC) address.

    Details-

    Actually, I am opening I2C1: in application that made call to the open operation which is present in I2C driver, and after getting success I am setting slave address(RTC address is 0x68) by passing IOCTL call as shown below -

    retval = DeviceIoControl(hI2C_frml, IOCTL_I2C_SET_SLAVE_ADDRESS,&sAddress, sizeof(sAddress), NULL, 0, NULL, NULL );

    it's also returning TRUE.

    Now, I want to access the sub register of RTC via I2C bus like SECONDS_REG with offset 0h....So, no need to add offset in base address of RTC because offset address is 0h and I can directly read the value of SECONDS_REG with 0x68 address...but I am unable to read any value and I am getting error as shown below -

     213343 PID:5300062 TID:5310062 In Main(): I2C file open successfully! 
     213343 PID:5300062 TID:5310062 Set_SlaveAddress(): Set successfully!
     213344 PID:5300062 TID:5310062 Main->SlaveAddress(): Slave address set successfully! 
     213345 PID:5300062 TID:5310062 Set_SubAddressMode(): Get Last Error 0!
     213346 PID:5300062 TID:5310062 Set_SubAddressMode(): Set successfully!
     213347 PID:5300062 TID:5310062 Main->AddressMode(): Address mode set successfully! 
     213847 PID:400002 TID:5310062 Read: Attempts = 2
     214347 PID:400002 TID:5310062 Read: Attempts = 3
     214847 PID:400002 TID:5310062 Read: Attempts = 4
     215347 PID:400002 TID:5310062 Read: Attempts = 5
     215847 PID:400002 TID:5310062 WARN: I2C: Read failed (slave addr=0x68, register=0x00000000)
     215847 PID:5300062 TID:5310062 Set_SlaveAddress(): Get Last Error 0!

    and I need to read DAYS_REG with address Ch then what will be the mechanism to add this offset in RTC base address....???????????

    and one more thing, I2C driver I have only 3 IOCTL calls as shown below -

    IOCTL_I2C_SET_SLAVE_ADDRESS // very much clear to me
    IOCTL_I2C_SET_SUBADDRESS_MODE // Not fully clear to me
    IOCTL_I2C_SET_BAUD_INDEX // Not clear to me

    for second IOCTL , I only got one thing it is used to set that which mode is used by slave for read or write (8 ,16, 32 byte) or some thing else????????????


    Wednesday, June 18, 2014 10:11 AM

All replies

  • Hi,

    Subaddress mode IOCTL is used to tell I2C Driver that  your device needs a one byte or two byte addressing.

    For example RTC Device requires a one byte subaddress as there will be less than 255 registers inside. But if you consider some EEPROM devices which will have more than 255 addresses and they will have 2/3 byte sub address.

    Baud Index is used to tell at what speed the peripheral is accessed. Ideal way to test is at slow speed mode that is < 100 KHz.

    Search for those IOCTL in your entire BSP you will find some header files and sample codes already used by some other drivers such as Audio and etc...

    What is the RTC Part number that you are using?

    The ideal sequence of IOCTLs might be I2COpen, SetSlaveAddress, SetSubAddressMode and then SetBaudRate.

    Regards,

    GSR


    • Edited by GSRid Wednesday, June 18, 2014 11:09 AM
    Wednesday, June 18, 2014 11:02 AM
  • Hello GSRid,

    Thanks for your valuable reply.. Now all IOCTL commands are clear to me.... but the post priority; how to read RTC register .........

    Wednesday, June 18, 2014 11:08 AM
  • The possible debug options would be

    • May be you can show us the code. If it is a standard BSP being used by any forum members they might provide some insights
    • Make sure that the RTC is connected on I2C1
    • If you have access to signals probe them using oscilloscope
    • Make sure the device address is correct

    What is the HW Platform and BSP that you are using?

    Regards,

    GSR

    Wednesday, June 18, 2014 11:23 AM
  • I am using AM335x BSP with Cortex A-8 processor and application code is shown below -

    // PhyI2C.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    #include "phyi2c.h"
    
    
    #define I2C_SUBADDRESS_MODE_32  4
    #define I2C_SUBADDRESS_MODE_16  2 //EEPROM takes 16 Byte addressing
    #define I2C_SUBADDRESS_MODE_8  1  //RTC mode
    
    
    
    int _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
    {
        HANDLE hI2Clocal; 
    	BOOL Status;
    	DWORD sAddress = 0x68; //
    	DWORD mode = I2C_SUBADDRESS_MODE_8;
    	char sBuffer[30] = "-- R --";
    	
    	hI2Clocal = Open_I2C();
    
    	if(hI2Clocal)
    	{
    		RETAILMSG(TRUE,(TEXT("In Main(): I2C file open successfully! \r\n")));
    
    		Status = Set_SlaveAddress(hI2Clocal, sAddress);
    		if(Status)
    		{
    			RETAILMSG(TRUE,(TEXT("Main->SlaveAddress(): Slave address set successfully! \r\n")));
    		}else
    		{
    			RETAILMSG(TRUE,(TEXT("Main->SlaveAddress(): Slave address not set! \r\n")));
    			exit(-1);
    		}
    
    
    		Status = Set_SubAddressMode(hI2Clocal, mode);
    		if(Status)
    		{
    			RETAILMSG(TRUE,(TEXT("Main->AddressMode(): Address mode set successfully! \r\n")));
    		}else
    		{
    			RETAILMSG(TRUE,(TEXT("Main->AddressMode(): Address mode not set! \r\n")));
    			exit(-1);
    		}
    
    			Status = ReadRTC(hI2Clocal);
    		///////*Status = WriteI2C(hI2Clocal, sBuffer);
    		//////if(Status)
    		//////{
    		//////	RETAILMSG(TRUE,(TEXT("Main->WriteI2C(): Data written successfully! \r\n")));
    		//////}else{
    		//////	RETAILMSG(TRUE,(TEXT("Main->WriteI2C(): Error in writing on EEPROM! \r\n")));
    		//////	exit(-1);
    		//////}*/
    
    	}else
    	{
    		RETAILMSG(TRUE,(TEXT("In Main(): Error in opening I2C file! \r\n")));
    		exit(-1);
    	}
    
    	return 0;
    }
    

    and corresponding header file is as shown below -

    #include "stdafx.h"
    #include "winbase.h"
    #include "winioctl.h"
    
    /********************************************************************
     **************			   Gobal Variables             **************
    *********************************************************************/
    
    HANDLE hI2Cglobal;
    DWORD retval;
    
    
    
    /********************************************************************
     **************			  Macros Definition            **************
    *********************************************************************/
    
    #define SUCCESS 1
    #define FAILURE	0
    
    
    #define IOCTL_I2C_SET_SUBADDRESS_MODE     \
        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0201, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_I2C_SET_SLAVE_ADDRESS     \
        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)
    
    
    
    /********************************************************************
    					Function Prototyping
    *********************************************************************/
    HANDLE Open_I2C();
    BOOL Set_SlaveAddress(HANDLE, DWORD);
    BOOL Set_SubAddressMode(HANDLE, DWORD);
    BOOL WriteI2C(HANDLE, char *);
    BOOL ReadRTC(HANDLE);
    
    
    /********************************************************************
     **************			   Creating/Opening File       **************
    *********************************************************************/
    
    
    HANDLE Open_I2C()
    {
    	hI2Cglobal = CreateFile(TEXT("I2C1:"),GENERIC_READ|GENERIC_WRITE,
    							FILE_SHARE_READ|FILE_SHARE_WRITE, 
    							NULL, OPEN_EXISTING, 0, 0 );
    
    	return hI2Cglobal;
    }
    
    BOOL Set_SlaveAddress(HANDLE hI2C_frml, DWORD sAddress)
    {	
    		
    	
    			retval = DeviceIoControl(hI2C_frml,
                                    IOCTL_I2C_SET_SLAVE_ADDRESS,
                                    &sAddress,
                                    sizeof(sAddress),
                                    NULL,
                                    0,
                                    NULL,
                                    NULL );
    
    	
    
    	
    
    	if(retval == SUCCESS)
    	{
    		RETAILMSG(TRUE,(TEXT("Set_SlaveAddress(): Set successfully!\r\n")));
    		return SUCCESS;
    
    	}
    	else
    	{
    		RETAILMSG(TRUE,(TEXT("Set_SlaveAddres():  Set unsuccessfull!\r\n")));
    		return FAILURE;
    	}
    	
    }
    
    BOOL Set_SubAddressMode(HANDLE hI2C_frml, DWORD sMode)
    {
    			
    	retval = DeviceIoControl(hI2C_frml,
    							IOCTL_I2C_SET_SUBADDRESS_MODE,
    							&sMode,
    							sizeof(sMode),
    							NULL,
    							0,
    							NULL,
    							NULL);
    								
    		
    
    	RETAILMSG(TRUE,(TEXT("Set_SubAddressMode(): Get Last Error %d!\r\n"),GetLastError()));
    
    	if(retval == SUCCESS)
    	{
    		RETAILMSG(TRUE,(TEXT("Set_SubAddressMode(): Set successfully!\r\n")));
    		return SUCCESS;
    
    	}
    	else
    	{
    		RETAILMSG(TRUE,(TEXT("Set_SubAddressMode():  Set unsuccessfull!\r\n")));
    		return FAILURE;
    	}
    
    }
    
    
    BOOL ReadRTC(HANDLE hI2C_frml)
    {
    
    	DWORD dwDataRead = 0;
    	char sBuffer[28];
    	DWORD sSize= strlen(sBuffer);
    	DWORD result = 0;
    
    	//RETAILMSG(TRUE,(TEXT("ReadI2C(): The received string is  %S!\r\n"),data_frml));
    	
    	retval = ReadFile(hI2C_frml, sBuffer, sSize, &dwDataRead, NULL);
    
    	RETAILMSG(TRUE,(TEXT("Set_SlaveAddress(): Get Last Error %d!\r\n"),GetLastError()));
    
    	if(retval == SUCCESS)
    	{
    		RETAILMSG(TRUE,(TEXT("WriteI2C(): Data written successfully!\r\n")));
    		RETAILMSG(TRUE,(TEXT("Read data is ---- %S \r\n"),sBuffer));
    		return SUCCESS;
    
    	}
    	else
    	{
    		RETAILMSG(TRUE,(TEXT("WriteI2C(): Error in writing data!\r\n")));
    		return FAILURE;
    	}
    }
    This is the code what I am using for accessing RTC register 

    Wednesday, June 18, 2014 11:32 AM
  • As of now two issues are observed

    • Speed setting is missing
    • In ReadRTC what is the strlen(sBuffer) that you are getting. In future you may get some issues with this

    What is the RTC Part number that are you using? Can you probe I2C1 lines?

    Regards,

    GSR

    Wednesday, June 18, 2014 11:49 AM
  • Hello GSRid,

    I don't think so I need any kind of speed setting because I2C has to read value from the register and speed setting is done for only transferring some thing; means @ what speed we are sending or receiving something with two machines ....................... 

    And, second strlen(sbuffer) will give the size of number of bytes I have to read................

    Wednesday, June 18, 2014 12:32 PM
  • I don't think so I need any kind of speed setting because I2C has to read value from the register and speed setting is done for only transferring some thing; means @ what speed we are sending or receiving something with two machines ....................... 

    If you read RTC register through I2C, it is I2C TRANSFER only.

    You are receiving something (RTC register value).


    Keshava G N,
    Member - Technical (Software),
    iWave Systems, Bangalore,
    http://iwavesystems.com ,
    mailto: keshavagnATiwavesystemsDOTcom .

    Thursday, June 19, 2014 5:08 AM
  • Hello Friends,

    Okay KeshavGN, Here I agree with you, I will try and update you guys with new status .....

    Thursday, June 19, 2014 1:30 PM
  • Hello Friends,

    @Keshava G N,

    After setting the transfer rate and passing it to driver with IOCTL_I2C_SET_BAUD_INDEX

    still I am getting a same error:

     215847 PID:400002 TID:5310062 WARN: I2C: Read failed (slave addr=0x68, register=0x00000000)
     215847 PID:5300062 TID:5310062 Set_SlaveAddress(): Get Last Error 0!
    Monday, June 23, 2014 4:09 AM
  • It looks like you're missing the piece that gets you to the subaddress within the I2C "file"

    After you've opened the "file", and used your IO control functions to set the I2C data rate, slave address, and subaddress mode (which looks like it should be an 8 bit subaddress mode and not the register you're trying to read), you need to access the "address" within the I2C file. 

    Something like:

         LONG lRegister = 0x01;  // Or whatever register in the RTC chip you need to read
         DWORD dPointer;

        dPointer = SetFilePointer(hI2C, lRegister, NULL, FILE_BEGIN);

    dPointer will be a -1 if this fails, or an offset.

    Then your ReadFile function should get you what you're looking for


    • Edited by Danno5060 Monday, December 12, 2016 8:58 PM
    Tuesday, November 8, 2016 6:36 PM