This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

I2C2 Bus Communication



We are having a terrible time trying to get the Zoom TMDSMEVM3530-L 1013403 Rev A development kit to communicate over I2C using Win CE 6.0. 

 

The goal is to communicate with an ALS light sensor connected to I2C2. Our sensor is at address 0x39 over we are starting with the test ap.

 

We have successfully installed the Win CE 6.0 development system and the BSP for the OMAP bard. We are compiling code and loading the new code in the development board and we can see our code changes take effect.

 

We have tried to use the example test code called I2C2DriverTest for testing I2C2 and we are not seeing this code communicate on the bus either. We have a very nice Tektronix 3014 scope that allows us to monitor I2C traffic on a bus. All we see is communication to a device at address 0x48 each time we touch the display. I assume this is traffic from the display system. We are connected to high density breakout board connector J17 pin 57 for I2C2_CLK and connector J18 pin 60 for I2C2_DATA signals.

 

I am including a copy of the code we are testing for reference. You can see how we are trying to configure this port and we have a while loop set up so it will continue to read and write data. We see no data.

 

My feeling is that we must have an issue with the CreateFile routine or the DeviceIoControl  which are both setting up the physical path to the device.

Has anyone else seen this issue or do you have any ideas what may be wrong?

// I2CDriverTestApp.cpp : Defines the entry point for the console application.
//

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <types.h>
#include <oal.h>
#include <oalex.h>
#include <ceddk.h>
#include <ceddkex.h>
#include <omap3430.h>
//#include <shellproc.h>
#include <ceddkex.h>
#include <initguid.h>
#include <omap3430_guid.h>
#include "..\..\..\public\common\oak\inc\windev.h"

#include <winioctl.h>

#include "stdafx.h"
//#include "..\..\..\Platform\LPD_OMAP35X_SOM\SRC\CSP\INC\I2C.h"
//#include <i2cproxy.h>
//#include <proxyapi.h>

//#include <twl.h>
//#include <twl4030.h>


//#include <ceddkex.h>

//#define FILE_DEVICE_UNKNOWN             0x00000022
//#define FILE_ANY_ACCESS                 0
#define METHOD_BUFFERED                 0

//#define CTL_CODE(DeviceType, Function, Method, Access) \
//                (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))

#define I2C_SUBADDRESS_MODE_8   1

//------------------------------------------------------------------------------

#define IOCTL_I2C_SET_SLAVE_ADDRESS   0x220800
//    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)

//------------------------------------------------------------------------------

#define IOCTL_I2C_SET_SUBADDRESS_MODE  0x220804
//    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0201, METHOD_BUFFERED, FILE_ANY_ACCESS)

 

int WINAPI
WinMain (
 HINSTANCE hInstance,
 HINSTANCE hPrevInstance,
    LPWSTR lpCmdLine,
 int nCmdShow)
{
 HANDLE hPort;
 DWORD dwSlaveAddr = 0x50;
 DWORD addrmode = I2C_SUBADDRESS_MODE_8;
 unsigned char outdata[6] = {1,2,3,4,5,6};
 unsigned char indata[6] = {0,0,0,0,0,0};
 DWORD len = 6;

 BOOL result;


    _tprintf(_T("Begin I2C2 Driver Test"));

 hPort = CreateFile(TEXT("I2C2:"),GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
   
 // set slave address of i2c device
 result = DeviceIoControl(hPort, IOCTL_I2C_SET_SLAVE_ADDRESS, &dwSlaveAddr,                             
                sizeof(dwSlaveAddr), NULL, 0, NULL, NULL);

 /*result = DeviceIoControl(hPort, IOCTL_I2C_SET_SUBADDRESS_MODE, &addrmode,                             
                sizeof(addrmode), NULL, 0, NULL, NULL);*/

 while(1){
  SetFilePointer(hPort, 0, NULL, FILE_BEGIN);

  result = WriteFile(hPort, outdata, 6, &len, 0);

  _tprintf(_T("len %d\n"),len);

  _tprintf(_T("Out Data %d %d %d %d %d %d\n"),outdata[0],outdata[1],outdata[2],outdata[3],outdata[4],outdata[5]);

  SetFilePointer(hPort,0, NULL, FILE_BEGIN);

  result = ReadFile(hPort, indata, 6, &len, 0);

  _tprintf(_T("len %d\n"),len);

  _tprintf(_T("In Data %d %d %d %d %d %d\n"),indata[0],indata[1],indata[2],indata[3],indata[4],indata[5]);

  if((indata[0] == outdata[0]) &&
     (indata[1] == outdata[1]) &&
     (indata[2] == outdata[2]) &&
     (indata[3] == outdata[3]) &&
     (indata[4] == outdata[4]) &&
     (indata[5] == outdata[5]))
  {
   _tprintf(_T("Test Success\n"));
  }
  else
  {
   _tprintf(_T("Test Failed\n"),len);
  }
 }//while
 getchar();

 return 0;
}

 

 

 

  • Hi Bob,

    It seems that you are doing the right thing when accessing the I2C driver. Could you post a log of what's happening when launching your application. Also I suggest you test the return code of the "CreateFile" function (hPort). If it returns "INVALID_HANDLE_VALUE", then you have an issue opening the I2C driver.

     

  •  

    Still have a problem getting data to flow on the I2C bus.

    Following your suggestion we fount the CreateFile was not returning a handle. After turning off sync bit we began to get a file pointer returned. I feel we are not being linked to the proper I2C2 bus though.

    Can you confirm the physical memor locations of:

    #define IOCTL_I2C_SET_SLAVE_ADDRESS   0x220800
    //    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)

    //------------------------------------------------------------------------------

    #define IOCTL_I2C_SET_SUBADDRESS_MODE  0x220804
    //    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0201, METHOD_BUFFERED, FILE_ANY_ACCESS)

     

     

    If these locations (0x220800 and 0x220804) are not correct this would explain the issue. Its not clear to me which I2C.H is the proper file to use with the 3530. I have tried to find the address in the OMAP3 data sheet and see much different physical locations for the base registers.

     

    We will work on making a log of the activity.

     

     

  • The I2C functions are built-in the kernel hence cannot be called from user space. This is why any call to the I2C driver must be done through the I2C proxy. This is what you do when you call "CreateFile(L"I2CX:,...". 

    The IOCTLs you should be calling are located under "TI_EVM_3530\SRC\TEST\COMMON\i2cproxy.h". You might need to include <winioctl.h> before as well for the "CTL_CODE" macro to work.

    If you want to make sure the right functions are called, you can put RETAILMSGs under the "I2C_IOControl()" function located in "TI_EVM_3530\SRC\TEST\I2CPROXY\i2cproxy.cpp".

    Let us know how it goes.

  •  

    We are running the code below as a user application. This code test every I2C address on I2C2 and we never see any traffic on the I2C2 BUS monitoring with a Scope both CLK and Data. We believe the code is setup per your suggestion.

    We must have something wrong. can you suggest something else we can try?

    Is there something else we should enable or do to get data flowing on the I2C2 port.

     

    By the way in the long run this will be supporting  phone display and it may need to be placed inthe Kernel. We have done this in linux but WinCe is proing to be more difficult.

    Thanks for any suggestions.

     

     

     

     

    // I2CDriverTestApp.cpp : Defines the entry point for the console application.
    //
    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    #include <types.h>
    #include <oal.h>
    #include <oalex.h>
    #include <ceddk.h>
    #include <ceddkex.h>
    #include <omap3430.h>
    //#include <shellproc.h>
    #include <ceddkex.h>
    #include <initguid.h>
    #include <omap3430_guid.h>
    #include "..\..\..\public\common\oak\inc\windev.h"

    #include <winioctl.h>

    #include "stdafx.h"
    #include "..\..\..\Platform\LPD_OMAP35X_SOM\SRC\CSP\INC\I2C.h"
    #include <i2cproxy.h>
    //#include <proxyapi.h>

    //#include <twl.h>
    //#include <twl4030.h>


    //#include <ceddkex.h>

    #define FILE_DEVICE_UNKNOWN             0x00000022
    #define FILE_ANY_ACCESS                 0
    #define METHOD_BUFFERED                 0

    #define CTL_CODE(DeviceType, Function, Method, Access) \
                    (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))

    #define I2C_SUBADDRESS_MODE_8   1

    //------------------------------------------------------------------------------

    //#define IOCTL_I2C_SET_SLAVE_ADDRESS   0x220800
    //    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)

    //------------------------------------------------------------------------------

    #define IOCTL_I2C_SET_SUBADDRESS_MODE  0x220804
    //    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0201, METHOD_BUFFERED, FILE_ANY_ACCESS)


    TCHAR szText[64];
    int WINAPI
    WinMain (
     HINSTANCE hInstance,
     HINSTANCE hPrevInstance,
        LPWSTR lpCmdLine,
     int nCmdShow)
    {
     HANDLE hPort;
     DWORD dwSlaveAddr; // = 0x39;
     DWORD addrmode = I2C_SUBADDRESS_MODE_8;
     unsigned char outdata[2] = {0,3};
     unsigned char indata[6] = {0,0,0,0,0,0};
     DWORD len = 6;

     BOOL result;


        _tprintf(_T("Begin I2C2 Driver Test"));

     hPort = CreateFile(TEXT("I2C2:"),GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,NULL);
     if( hPort == INVALID_HANDLE_VALUE) {
      MessageBox(NULL, L"unable open i2c2 port", NULL, NULL);
      CloseHandle(hPort);
      return 0;
     }
     
     /*wsprintf(szText, TEXT("Open I2C2 GetLastError %d"), GetLastError());
        MessageBox(NULL,szText,NULL,NULL);*/

     for (dwSlaveAddr = 0x00; dwSlaveAddr <= 256; dwSlaveAddr++)
     {
      // set slave address of i2c device
      result = DeviceIoControl(hPort, IOCTL_I2C_SET_SLAVE_ADDRESS, &dwSlaveAddr,                             
         sizeof(dwSlaveAddr), NULL, 0, NULL, NULL);
      if (!result) {
       MessageBox(NULL, L"DeviceIoControl failed", NULL, NULL);
       CloseHandle(hPort);
      }
      
       SetFilePointer(hPort, 0, NULL, FILE_BEGIN);

       result = WriteFile(hPort, outdata, 2, &len, 0);
       if (result) {
        wsprintf(szText, TEXT("add %x"), &dwSlaveAddr);
        MessageBox(NULL,szText,NULL,NULL);

        SetFilePointer(hPort,0, NULL, FILE_BEGIN);
        result = ReadFile(hPort, indata, 6, &len, 0);
        if (result) {
         MessageBox(NULL, L"Test Success", NULL, NULL);
        }
       }
     }//for loop

     return 0;
    }

     

  • Are you sure you have the I2C proxy code included?  It is under the TEST tree of the BSP.

  • We finally determined the schematics provided for the OMAP Zoom board were not correct. The I2C1 and I2C2 wiring is reversed.

    Hopfully this information will help others.

  • As a continuation to the I2C communication issue we would like to post the following.....

     

    We must implement an interrupt in a I2C device driver on TI omap35x. Why you may ask. We are working on a sensor that will be used to control the screen brightness of a platform. This is a kernel mode task and needs to run with an interrupt.

    We are trying to use the hardware interrupt called GPIO98 AKA know as IRQ_GPIO_98.


    We used function called KernelIoControl with an IO control code of IOCTL_HAL_REQUEST_SYSINTR to register IRQ/SYSINTR mappings then used Initialize interrupt and associate the SYSINTR value with the event. At this point, I get an error message SYSINTR out of range. 

    Is there a location in the BSP that we must modify to allow the use of a particular interrupt?

     

    We have been referencing a document that looks stright forward on implimenting a hardware intterup but not able to get it working. It is not clear how to impliment the hardware interrupt.

    Can anyone offer any suggestions or references on this?

  • You really don't need to request a sysintr and all that as the GPIO driver takes care of all the dirty work.

    Just do something like:

    pDevice->

    hGPIO = GPIOOpen();

    GPIOSetMode(pDevice->hGPIO, pDevice->nGPIOIrq1, GPIO_DIR_INPUT|GPIO_INT_LOW_HIGH);

    pDevice->hIntrEventIrq1 = CreateEvent(NULL, FALSE, FALSE, NULL);

     

     

     

     

     

     

    // Initialize interrupt

     

     

    if (!GPIOInterruptInitialize(pDevice->hGPIO, pDevice->nGPIOIrq1, pDevice->hIntrEventIrq1))

    {

    DEBUGMSG (ZONE_ERROR, (L

    "ERRORInterruptInitialize IRQ1 failed\r\n"));

     

     

    goto cleanUp;

    }

    ...

    I omitted some steps but you get the idea.

     

    DV

     

  • We are just not getting the interrupt to work.

    Here is some test code and debug output which should tell us an interrupt has fired. We test this by grounding the INTB pin while it has a pullup resistor on it. No interrupt is seen.

    Here is the code

     

    DWORD dwLogintr = IRQ_GPIO_167;

    hGPIO = GPIOOpen();

    if (hGPIO == NULL)

    {

    wsprintf(Temp,L"Failed open GPIO device driver");

    OutputDebugString(Temp);

    }

    // Setup ASL_IRQ for input mode, falling edge detect, debounce enable

    GPIOSetMode(hGPIO, dwLogintr, GPIO_DIR_INPUT | GPIO_INT_LOW);

    // Create an Event

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (hEvent == NULL)

    {

    wsprintf(Temp,L"CreateEvent failed (GetLastError() = 0x%08x)", GetLastError());

    OutputDebugString(Temp);

    }

    // Get sysintr values from the OAL for als IRQ interrupt

    bResult = KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwLogintr, sizeof(dwLogintr), &dwSysintr, sizeof(dwSysintr), NULL) ;

    if (bResult == FALSE && dwSysintr != -1){

    wsprintf(Temp,L"Failed register dwtaosirq with the Kernel");

    OutputDebugString(Temp);

    return bResult;

    }

    else {

    wsprintf(Temp,L"dwLogintr = %d sysintr = %d", dwLogintr, dwSysintr);

    OutputDebugString(Temp);

    }

    if(!InterruptInitialize( dwSysintr, hEvent, NULL, 0))

    {

    wsprintf(Temp,L"Failed to get sysintr value (GetLastError() = 0x%08x)", GetLastError());

    OutputDebugString(Temp);

    }

    else {

    wsprintf(Temp,L"InterruptInitialize passed");

    OutputDebugString(Temp);

    }

    RetVal = WaitForSingleObject(hEvent, INFINITE);

    if( RetVal == WAIT_OBJECT_0 ) //WAIT_OBJECT_0 indicates the pHandles array index of the object that satisfied the wait.

    {

    wsprintf(Temp,L"Test successful");

    OutputDebugString(Temp);

    InterruptDone( dwSysintr );

    }

    else if( RetVal == WAIT_TIMEOUT ) //The time-out interval elapsed and the conditions specified by the bWaitAll and dwWakeMask parameters were not satisfied.

    {

    wsprintf(Temp,L"Wait timeout %d", RetVal);

    OutputDebugString(Temp);

    }

     

    Here is the output.

     

    67920 PID:400002 TID:fe0002 OSAXST1: >>> Loading Module 'taos.dll' (0x8375CCE4) at address 0xC1060000-0xC1067000 in Process 'NK.EXE' (0x829ACAA0)

    67920 PID:400002 TID:fe0002 taos - DLL_PROCESS_ATTACH

    67920 PID:400002 TID:fe0002 Kernel DLL 'taos.dll' needs thread creation/deletion notification

    67920 PID:400002 TID:fe0002 dwLogintr = 295 sysintr = 23

    67920 PID:400002 TID:fe0002 InterruptInitialize passed

    67920 PID:1650002 TID:1050002 [NOTIFY] HandleSystemEvent 7 /ADD I2C2:

    67920 PID:1650002 TID:1050002 [NOTIFY] HandleSystemEvent 7 /ADD I2C3:

    68161 PID:400002 TID:11c0006 VMini:: Detected DHCP [DISCOVER]

    68161 PID:400002 TID:11c0006 VMini:: Detected DHCP [REQUEST]

    68161 PID:400002 TID:11c0006 LanaUp: (NB) pLana D17FA040 (1) up Addr 68C9A8C0 Mask FFFFFF Bcast FFC9A8C0

    69174 PID:400002 TID:2e9000e +RDR:NetBIOSNotifyFunc: Lana 1, flags: 0x3

    69174 PID:400002 TID:2e9000e +RDR:NetupIndication, lana 1

    69174 PID:400002 TID:2e9000e +RDR:BindToNet: lananum: 1

    69174 PID:400002 TID:2e9000e +RDR:BindToNetbiosTransport

    69174 PID:400002 TID:2e9000e -RDR:BindToNet successful for lana 1

    69174 PID:400002 TID:2e9000e -RDR:NetBIOSNotifyFunc: Lana 1

    69174 PID:400002 TID:355000e +RDR:RdrUIThread starting

    69537 PID:400002 TID:3a3000a OSAXST1: >>> Loading Module 'ssllsp.dll' (0x8376C51C) at address 0x40370000-0x40387000 in Process 'NK.EXE' (0x829ACAA0)

    69578 PID:3f30002 TID:3a3000a OSAXST1: >>> Loading Module 'ssllsp.dll' (0x8376C51C) at address 0x40370000-0x40387000 in Process 'udevice.exe' (0x837198DC)

    70185 PID:400002 TID:3a3000a OSAXST1: >>> Loading Module 'wspm.dll' (0x8377E1F8) at address 0x40330000-0x40338000 in Process 'NK.EXE' (0x829ACAA0)

    70185 PID:3f30002 TID:3a3000a OSAXST1: >>> Loading Module 'wspm.dll' (0x8377E1F8) at address 0x40330000-0x40338000 in Process 'udevice.exe' (0x837198DC)

    71174 PID:1650002 TID:3ae0026 [NOTIFY] HandleSystemEvent 5 none

    71184 PID:1650002 TID:3ae0026 [NOTIFY] HandleSystemEvent 5 none

    71871 PID:400002 TID:3a3000a OSAXST1: >>> Loading Module 'nspm.dll' (0x8379945C) at address 0x40340000-0x40349000 in Process 'NK.EXE' (0x829ACAA0)

    71972 PID:3f30002 TID:3a3000a OSAXST1: >>> Loading Module 'nspm.dll' (0x8379945C) at address 0x40340000-0x40349000 in Process 'udevice.exe' (0x837198DC)

    72077 PID:400002 TID:3a3000a Ipv6Hlp::

    72077 PID:400002 TID:3a3000a GetAddrInfoW for [6to4.ipv6.microsoft.com.] returned [11001]

    72208 PID:400002 TID:3ea0002 Ipv6Hlp::

    72208 PID:400002 TID:3ea0002 GetAddrInfoW for [6to4.ipv6.microsoft.com.] returned [11001]

    129177 PID:400002 TID:355000e !RdrUIThread: SH_WMGR not found

     

  • As I stated before you DO NOT need to call KernalIoControl, you are making it much harder then it really is.

    Also you are calling set mode with IRQ_GPIO_167 instead of GPIO_167 and not calling GPIOInterruptInitialize.

    It should be something like...

    hGPIO = OpenGPIO();

    GPIOSetMode(hGPIO, GPIO_167, GPIO_DIR_INPUT | GPIO_INT_LOW);

     

     

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

     

    GPIOInterruptInitialize(hGPIO, GPIO_167, hEvent)