6410操作24C02驱动bug批改及测试

6410操作24C02驱动bug修改及测试

上一篇文章中将24C02电路搭建起来了,参考

http://blog.csdn.net/lyx123/article/details/7884026

现在调试驱动程序和测试,在网上下载了测试程序,地址为http://download.csdn.net/detail/LH806732/1489011

发现操作不了,不能写也不能读,程序作者介绍说:“本测试程序专门针对S3C6410读写AT24C02的IIC驱动的测试程序。 三星提供的IIC驱动有点问题,需要修改,要不然测试会发生数据异常。”

所以,必须修改驱动程序。

 

由此,参考了网上的牛人程序,修改为如下:

1.s3c6410_iic_lib.cpp

//
// Copyright (c) Samsung Electronics. Co. LTD.  All rights reserved.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
*/
/**************************************************************************************
*
*    Project Name : IIC Driver
*
*    Project Description :
*        This software is PDD layer for IIC Samsung driver.
*
*--------------------------------------------------
*
*    File Name : s3c6410_iic_lib.cpp
*
*    File Description : This file implements PDD layer functions
*
**************************************************************************************/

#include <bsp.h>
#include <types.h>
#include <linklist.h>
#include <devload.h>
#include <pm.h>
#include <DrvLib.h>
#include <iic_mdd.h>
#include <iic_pdd.h>

#define DEBUG   0

#if DEBUG
#define ZONE_ERROR          DEBUGZONE(0)
#define ZONE_WARN           DEBUGZONE(1)
#define ZONE_FUNCTION       DEBUGZONE(2)
#define ZONE_INIT           DEBUGZONE(3)
#define ZONE_INFO           DEBUGZONE(4)
#define ZONE_IST            DEBUGZONE(5)

extern DBGPARAM dpCurSettings;
#endif

#define DEFAULT_FILTER_ENABLE        1
#define DEFAULT_DELAY                Clk_0
#define DEFAULT_CLOCK                3000
#define DEFAULT_MODE                 Master_transmit

#define TIMEOUT_MS_TX                3000
#define TIMEOUT_MS_RX                3000

#define IIC_POWER_ON   (1<<17)    // PCLK_GATE bit 17

#define UnusedParameter(x)  x = x

#define ICC_ST_IDLE                 0x00
#define ICC_ST_WRADDR               0x02

static volatile S3C6410_GPIO_REG     *g_pGPIOReg        = NULL;
static volatile S3C6410_SYSCON_REG   *g_pSYSCONReg      = NULL;
static volatile S3C6410_IIC_REG      *g_pIICReg         = NULL;

static HANDLE                g_hTransferDone;        // transmit event done, both rx and tx
static HANDLE                g_hTransferEvent;        // IIC event, both rx and tx
static HANDLE                g_hTransferThread;        // transmit thread, both rx and tx

static DWORD                 g_IntrIIC         = SYSINTR_NOP;

static PHW_OPEN_INFO         g_OwnerContext = NULL;

static PUCHAR                g_pcIIC_BUFFER=NULL;
static UINT32                g_uIIC_PT=0;
static UINT32                g_uIIC_DATALEN=0;

//static UCHAR     g_IIC_IST_BUFFER[4096];

static BOOL    MapVirtualAddress(void);
static void    InitializeGPIOPort(void);
static void    CalculateClockSet(PHW_OPEN_INFO pOpenContext);
static BOOL    WaitForReg(PVOID pRegAddress, UINT32 tMask, UINT32 tWaitForEqual, DWORD dwTimeout);
static DWORD   IIC_IST(LPVOID Context);

//////////
// Function Name : HW_Init
// Function Description : IIC device H/W initialization.
// Input :     PHW_INIT_INFO    pInitContext
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL         HW_Init (PHW_INIT_INFO pInitContext)
{
    BOOL    RetVal           = TRUE;        // Initialize to success
    UINT32     Irq;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_Init(0x%X)\r\n"),
               pInitContext));

    if(!MapVirtualAddress())
    {
        RetVal = FALSE;
        goto CleanUp;
    }

    InitializeGPIOPort();

    /* Create tx and rx events. Check return.
     */
    g_hTransferEvent = CreateEvent(0,FALSE,FALSE,NULL);
    if ( !g_hTransferEvent ) {
        DEBUGMSG(ZONE_ERROR,
                 (TEXT("Error creating event, HW_Init failed\n\r")));
        RetVal = FALSE;
        goto CleanUp;
    }

    g_hTransferDone = CreateEvent(0,FALSE,FALSE,NULL);
    if ( !g_hTransferDone ) {
        DEBUGMSG(ZONE_ERROR,
                 (TEXT("Error creating done event, HW_Init failed\n\r")));
        RetVal = FALSE;
        goto CleanUp;
    }

    // Obtain sysintr values from the OAL for the IIC interrupt.
    //
    Irq = IRQ_I2C;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(UINT32), &g_IntrIIC, sizeof(UINT32), NULL))
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Failed to request the IIC sysintr.\r\n")));
        g_IntrIIC = SYSINTR_UNDEFINED;
        RetVal = FALSE;
        goto CleanUp;
    }

    DEBUGMSG(ZONE_INFO, (TEXT("IIC IRQ mapping: [IRQ:%d->sysIRQ:%d].\r\n"), Irq, g_IntrIIC));

    // initialize the interrupt
    if( !InterruptInitialize(g_IntrIIC, g_hTransferEvent, NULL, 0) )
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("HW_Init ERROR: Unable to initialize interrupt: %u\r\n"), GetLastError()));
        RetVal = FALSE;
        goto CleanUp;
    }


    // create the IST
    if ( (g_hTransferThread = CreateThread(NULL, 0, IIC_IST, (LPVOID)pInitContext, 0, NULL)) == NULL)
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("HW_Init ERROR: Unable to create IST: %u\r\n"), GetLastError()));
        RetVal = FALSE;
        goto CleanUp;
    }

    if ( !CeSetThreadPriority(g_hTransferThread, pInitContext->Priority256)) {

        DEBUGMSG(ZONE_ERROR,(TEXT("HW_Init ERROR: CeSetThreadPriority ERROR:%d\n"), GetLastError()));
        RetVal = FALSE;
        goto CleanUp;
    }

CleanUp:
    DEBUGMSG (ZONE_FUNCTION|(RetVal == FALSE?ZONE_ERROR:0),
              (TEXT("-HW_Init %s Ecode=%d\r\n"),
               (RetVal == TRUE) ? TEXT("Success") : TEXT("Error"),
               GetLastError()));
    return (RetVal);
}


//////////
// Function Name : HW_Deinit
// Function Description : IIC device H/W de-initialization.
// Input :     PHW_INIT_INFO    pInitContext
// Output :   VOID
// Version : v0.1
BOOL         HW_Deinit (PHW_INIT_INFO pInitContext)
{
 BOOL            RetVal           = TRUE;        // Initialize to success

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_Deinit(0x%X)\r\n"),
               pInitContext));

    if (g_hTransferDone)
    {
        CloseHandle(g_hTransferDone);
        g_hTransferDone = NULL;
    }

    if (g_IntrIIC != SYSINTR_UNDEFINED)
    {
        InterruptDisable(g_IntrIIC);
    }
    if (g_hTransferEvent)
    {
        CloseHandle(g_hTransferEvent);
        g_hTransferEvent = NULL;
    }
    if (g_IntrIIC != SYSINTR_UNDEFINED)
    {
        KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &g_IntrIIC, sizeof(DWORD), NULL, 0, NULL);
    }
    g_IntrIIC = SYSINTR_UNDEFINED;

    if (g_hTransferThread)
    {
        CloseHandle(g_hTransferThread);
        g_hTransferThread = NULL;
    }
    if (g_pGPIOReg)
    {
        DrvLib_UnmapIoSpace((PVOID)g_pGPIOReg);
        g_pGPIOReg = NULL;
    }

    if (g_pSYSCONReg)
    {
        DrvLib_UnmapIoSpace((PVOID)g_pSYSCONReg);
        g_pSYSCONReg = NULL;
    }

    if (g_pIICReg)
    {
        DrvLib_UnmapIoSpace((PVOID)g_pIICReg);
        g_pIICReg = NULL;
    }
/*
    if (g_pGPIOReg)
    {
        MmUnmapIoSpace((PVOID)g_pGPIOReg, sizeof(S3C6410_GPIO_REG));
        g_pGPIOReg = NULL;
    }

    if (g_pSYSCONReg)
    {
        MmUnmapIoSpace((PVOID)g_pSYSCONReg, sizeof(S3C6410_SYSCON_REG));
        g_pSYSCONReg = NULL;
    }

    if (g_pIICReg)
    {
        MmUnmapIoSpace((PVOID)g_pIICReg, sizeof(S3C6410_IIC_REG));
        g_pIICReg = NULL;
    }
    */
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-HW_Deinit\r\n")));

 return (RetVal);

}
//////////
// Function Name : MapVirtualAddress
// Function Description : Mapping Virtual address of Registers.
// Input :
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL         MapVirtualAddress(void)
{
    BOOL            RetVal           = TRUE;        // Initialize to success

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("++%s\r\n"), __FUNCTION__));

    // GPIO SFR
    g_pGPIOReg = (S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO, sizeof(S3C6410_GPIO_REG), FALSE);
    if (g_pGPIOReg == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (_T("MapVirtualAddress() : g_pGPIOReg DrvLib_MapIoSpace() Failed \n\r")));
        return FALSE;;
    }

    // SYSCON SFR
    g_pSYSCONReg = (S3C6410_SYSCON_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_SYSCON, sizeof(S3C6410_SYSCON_REG), FALSE);
    if (g_pSYSCONReg == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (_T("MapVirtualAddress() : g_pSYSCONReg DrvLib_MapIoSpace() Failed \n\r")));
        return FALSE;;
    }

    // IIC SFR
    g_pIICReg = (S3C6410_IIC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_IICBUS, sizeof(S3C6410_IIC_REG), FALSE);
    if (g_pIICReg == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (_T("MapVirtualAddress() : g_pIICReg DrvLib_MapIoSpace() Failed \n\r")));
        return FALSE;;
    }

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("--%s\r\n"),__FUNCTION__));
    return (RetVal);
}
/*
//////////
// Function Name : MapVirtualAddress
// Function Description : Mapping Virtual address of Registers.
// Input :
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL         MapVirtualAddress(void)
{
    BOOL            RetVal           = TRUE;        // Initialize to success
    PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("++%s\r\n"), __FUNCTION__));

    // GPIO SFR
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_GPIO;
    g_pGPIOReg = (S3C6410_GPIO_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_GPIO_REG), FALSE);
    if (g_pGPIOReg == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (_T("%s : g_pGPIOReg MmMapIoSpace() Failed \n\r"), __FUNCTION__));
        return FALSE;
    }

    // SYSCON SFR
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_SYSCON;
    g_pSYSCONReg = (S3C6410_SYSCON_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_SYSCON_REG), FALSE);
    if (g_pSYSCONReg == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (_T("%s : g_pSYSCONReg MmMapIoSpace() Failed \n\r"), __FUNCTION__));
        return FALSE;
    }

    // IIC SFR
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_IICBUS;
    g_pIICReg = (S3C6410_IIC_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_IIC_REG), FALSE);
    if (g_pIICReg == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (_T("%s : g_pIICReg MmMapIoSpace() Failed \n\r"), __FUNCTION__));
        return FALSE;
    }

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("--%s\r\n"),__FUNCTION__));
    return (RetVal);
}
*/

//////////
// Function Name : InitializeGPIOPort
// Function Description : Initializing GPIO port for IIC.
// Input :
// Output :
// Version : v0.9
void     InitializeGPIOPort(void)
{
    // set SCL GPB5
    g_pGPIOReg->GPBCON = (g_pGPIOReg->GPBCON & ~(0xf<<20)) | (0x2<<20);

    // set SDA GPB6
    g_pGPIOReg->GPBCON = (g_pGPIOReg->GPBCON & ~(0xf<<24)) | (0x2<<24);

    // set SCL pull-up
    g_pGPIOReg->GPBPUD = (g_pGPIOReg->GPBPUD & ~(0x3<<10)) | (0x0<<10);

    // set SDA pull-up
    g_pGPIOReg->GPBPUD = (g_pGPIOReg->GPBPUD & ~(0x3<<12)) | (0x0<<12);
}

//////////
// Function Name : HW_PowerUp
// Function Description : Power control for IIC.
// Input :     PHW_INIT_INFO pInitContext
// Output : The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.9
BOOL
HW_PowerUp(
    PHW_INIT_INFO pInitContext    /* value from I2C_Init */
   )
{
    UnusedParameter(pInitContext);
    DEBUGMSG(ZONE_FUNCTION,(TEXT("+[IIC]HW_PowerUp\r\n")));
    g_pSYSCONReg->PCLK_GATE |= IIC_POWER_ON;
    DEBUGMSG(ZONE_FUNCTION,(TEXT("-[IIC]HW_PowerUp\r\n")));
    return TRUE;
}

//////////
// Function Name : HW_PowerDown
// Function Description : Power control for IIC.
// Input :     PHW_INIT_INFO pInitContext
// Output : The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.9
BOOL
HW_PowerDown(
    PHW_INIT_INFO pInitContext    /* value from I2C_Init */
   )
{
    UnusedParameter(pInitContext);
    DEBUGMSG(ZONE_FUNCTION,(TEXT("+[IIC]HW_PowerDown\r\n")));
    g_pSYSCONReg->PCLK_GATE &= ~IIC_POWER_ON;

    g_OwnerContext = NULL; // This is for Power Management. When Power up, IIC set register again.
    DEBUGMSG(ZONE_FUNCTION,(TEXT("-[IIC]HW_PowerDown\r\n")));
    return TRUE;
}

//////////
// Function Name : HW_OpenFirst
// Function Description : IIC device dirver is opened first.
// Input :     PHW_OPEN_INFO    pOpenContext
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL         HW_OpenFirst (PHW_OPEN_INFO pOpenContext)
{
    BOOL            RetVal          =     TRUE;        // Initialize to success
    PHW_INIT_INFO    pInitContext    =    pOpenContext->pInitContext;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_OpenFirst(0x%X)\r\n"),
               pOpenContext));

    // slave address setting
    pInitContext->PDDCommonVal.SlaveAddress = DEFAULT_SLAVE_ADDRESS;
    pInitContext->PDDCommonVal.InterruptEnable = DEFAULT_INTERRUPT_ENABLE;

    DEBUGMSG (ZONE_FUNCTION|(RetVal == FALSE?ZONE_ERROR:0),
              (TEXT("-HW_OpenFirst %s Ecode=%d\r\n"),
               (RetVal == TRUE) ? TEXT("Success") : TEXT("Error"),
               GetLastError()));
    return (RetVal);
}

//////////
// Function Name : HW_CloseLast
// Function Description : IIC device dirver is closed last.
// Input :     PHW_OPEN_INFO    pOpenContext
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL         HW_CloseLast (PHW_OPEN_INFO pOpenContext)
{
    BOOL    RetVal           = TRUE;        // Initialize to success

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_CloseLast(0x%X)\r\n"),
               pOpenContext));

 

    DEBUGMSG (ZONE_FUNCTION|(RetVal == FALSE?ZONE_ERROR:0),
              (TEXT("-HW_CloseLast %s Ecode=%d\r\n"),
               (RetVal == TRUE) ? TEXT("Success") : TEXT("Error"),
               GetLastError()));
    return (RetVal);
}

//////////
// Function Name : HW_Open
// Function Description : IIC device dirver is opened.
// Input :     PHW_OPEN_INFO    pOpenContext
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL         HW_Open         (PHW_OPEN_INFO pOpenContext)
{
    BOOL            RetVal       = TRUE;        // Initialize to success
    PHW_INIT_INFO    pInitContext = pOpenContext->pInitContext;

    DEBUGCHK(pOpenContext!= NULL);

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_Open(0x%X)\r\n"),
               pOpenContext));
//    RETAILMSG (1,
//              (TEXT("IIC0 +HW_Open(0x%X)\r\n"),
//               pOpenContext));

    pOpenContext->PDDContextVal.Clock               = DEFAULT_CLOCK;
    pOpenContext->PDDContextVal.ModeSel             = DEFAULT_MODE;
    pOpenContext->PDDContextVal.FilterEnable        = DEFAULT_FILTER_ENABLE;
    pOpenContext->PDDContextVal.Delay               = DEFAULT_DELAY;

    CalculateClockSet(pOpenContext);

    pOpenContext->DirtyBit = TRUE;

    HW_SetRegister(pOpenContext);


    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-HW_Open(0x%X)\r\n"),
               pOpenContext));
    return (RetVal);
}


//////////
// Function Name : HW_Close
// Function Description : IIC device dirver is closed.
// Input :     PHW_OPEN_INFO    pOpenContext
// Output :The return is a BOOL, representing success (TRUE) or failure (FALSE).
// Version : v0.1
BOOL         HW_Close     (PHW_OPEN_INFO pOpenContext)
{
    BOOL    RetVal           = TRUE;        // Initialize to success
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_Close(0x%X)\r\n"),
               pOpenContext));

//    RETAILMSG (1,
//              (TEXT("IIC0 -HW_Close(0x%X)\r\n"),
//               pOpenContext));
    return (RetVal);
}

//////////
// Function Name : CalculateClockSet
// Function Description : Calculate clock and save its setting value in ClkSrc, ClkDiv.
// Input : PHW_OPEN_INFO pOpenContext
// Output :
// Version : v1.0
void    CalculateClockSet(PHW_OPEN_INFO pOpenContext)
{
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+CalculateClockSet(0x%X), Clock(%d)\r\n"),
               pOpenContext, pOpenContext->PDDContextVal.Clock));

    DEBUGCHK(pOpenContext->PDDContextVal.Clock!= NULL);

    if (((S3C6410_PCLK>>4)/pOpenContext->PDDContextVal.Clock)>0xf)
    {
            pOpenContext->PDDContextVal.ClockSel    =    1;
            pOpenContext->PDDContextVal.ClockDiv    =    ((S3C6410_PCLK>>9)/pOpenContext->PDDContextVal.Clock);        //    PCLK/512/freq
            if(pOpenContext->PDDContextVal.ClockDiv != 0)
                pOpenContext->PDDContextVal.ClockDiv -=1;
    }
    else
    {
            pOpenContext->PDDContextVal.ClockSel    =    0;
            pOpenContext->PDDContextVal.ClockDiv    =    ((S3C6410_PCLK>>4)/pOpenContext->PDDContextVal.Clock);        //    PCLK/16/freq
            if(pOpenContext->PDDContextVal.ClockDiv != 0)
                pOpenContext->PDDContextVal.ClockDiv -=1;
    }

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-CalculateClockSet(0x%X), ClockSel(%d), ClockDiv(%d)\r\n"),
               pOpenContext, pOpenContext->PDDContextVal.ClockSel, pOpenContext->PDDContextVal.ClockDiv));
}

//////////
// Function Name : HW_SetRegister
// Function Description : Set registers when Device Owner is changed.
// Input : PHW_OPEN_INFO pOpenContext
// Output :
// Version : v0.5
VOID         HW_SetRegister (PHW_OPEN_INFO pOpenContext)
{
    PHW_INIT_INFO    pInitContext = pOpenContext->pInitContext;

    DEBUGCHK(g_pIICReg!= NULL);

    if(g_OwnerContext != pOpenContext || pOpenContext->DirtyBit == TRUE)
    {
        DEBUGMSG (ZONE_FUNCTION,
                  (TEXT("+HW_SetRegister(0x%X)\r\n"),
                   pOpenContext));
        g_pIICReg->IICADD = pOpenContext->pInitContext->PDDCommonVal.SlaveAddress;
        g_pIICReg->IICSTAT = (g_pIICReg->IICSTAT & ~(0x3<<6)) | (1<<4) | (pOpenContext->PDDContextVal.ModeSel<<6);
        g_pIICReg->IICLC = (pOpenContext->PDDContextVal.FilterEnable<<2) | (pOpenContext->PDDContextVal.Delay);
        g_pIICReg->IICCON = (pOpenContext->PDDContextVal.ClockSel << 6) | (pInitContext->PDDCommonVal.InterruptEnable << 5) |
                                (pOpenContext->PDDContextVal.ClockDiv & 0xf);

        g_OwnerContext = pOpenContext;
        pOpenContext->DirtyBit = FALSE;
        DEBUGMSG (ZONE_FUNCTION,
                  (TEXT("-HW_SetRegister(0x%X)\r\n"),
                   pOpenContext));
    }
}

//////////
// Function Name : HW_SetClock
// Function Description : Set clock, this is called by IIC_IOControl
// Input : PHW_OPEN_INFO pOpenContext
// Output :
// Version : v0.5
VOID         HW_SetClock (PHW_OPEN_INFO pOpenContext)
{
    CalculateClockSet(pOpenContext);
}

//////////
// Function Name : HW_Read
// Function Description : IIC Read Operation, Sync function, so wait for transfer done or time out.
// Input : PHW_OPEN_INFO pOpenContext
//           PIIC_IO_DESC pOutData
// Output :
// Version : v0.5
BOOL        HW_Read             (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData ,PIIC_IO_DESC pOutData)
{
    HRESULT hr;
    BOOL    retVal           = TRUE;        // Initialize to success
    PBYTE     MappedEmbedded;
    PBYTE     Marshalled;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_Read(0x%X)\r\n"),
               pOpenContext));

    HW_SetRegister(pOpenContext);

    HW_Write(pOpenContext, pInData);

    ResetEvent(g_hTransferDone);

    //    Wait until IIC bus is free.
    if(!WaitForReg((PVOID)&(g_pIICReg->IICSTAT), (1<<5), 0x0, TIMEOUT_MS_RX))
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]IIS BUS is busy.\r\n")));
        retVal = FALSE;
        goto CleanUp;
    }

    //  内核地址映射
    hr = CeOpenCallerBuffer((PVOID*) &MappedEmbedded, pOutData->Data, pOutData->Count, ARG_O_PTR, FALSE);
    hr = CeAllocAsynchronousBuffer((PVOID*) &Marshalled, MappedEmbedded, pOutData->Count, ARG_O_PTR);

    g_pcIIC_BUFFER    =    Marshalled;
    g_uIIC_PT         =    0;
    g_uIIC_DATALEN    =    pOutData->Count;

    g_pIICReg->IICCON |= (1<<7);        //    Ack generation Enable

    g_pIICReg->IICDS  =     pOutData->SlaveAddress;

    g_pIICReg->IICSTAT = MRX_START;

    if(WaitForSingleObject(g_hTransferDone, TIMEOUT_MS_RX) == WAIT_TIMEOUT)
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]RX Time out.\r\n")));
        retVal = FALSE;
    }

    hr = CeFreeAsynchronousBuffer((PVOID)Marshalled, MappedEmbedded, pOutData->Count, ARG_O_PTR);
    hr = CeCloseCallerBuffer((PVOID)  MappedEmbedded, pOutData->Data, pOutData->Count, ARG_O_PTR);

CleanUp:
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_Read(0x%X)\r\n"),
               pOpenContext));
    return retVal;
}

//////////
// Function Name : HW_Write
// Function Description : IIC Write Operation, Sync function, so wait for transfer done or time out.
// Input : PHW_OPEN_INFO pOpenContext
//           PIIC_IO_DESC pInData
// Output :
// Version : v0.5
BOOL        HW_Write        (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData)
{
    HRESULT   hr;
    BOOL      retVal           = TRUE;        // Initialize to success
    PBYTE     MappedEmbedded;
    PBYTE     Marshalled;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_Write(0x%X)\r\n"),
               pOpenContext));

    HW_SetRegister(pOpenContext);

    ResetEvent(g_hTransferDone);
    //    Wait until IIC bus is free.
    if(!WaitForReg((PVOID)&(g_pIICReg->IICSTAT), (1<<5), 0x0, TIMEOUT_MS_TX))
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]IIC BUS is busy.\r\n")));
        return FALSE;
    }

    hr = CeOpenCallerBuffer((PVOID*) &MappedEmbedded, pInData->Data, pInData->Count, ARG_I_PTR, FALSE);
    hr = CeAllocAsynchronousBuffer((PVOID*) &Marshalled, MappedEmbedded, pInData->Count, ARG_I_PTR);

    g_pcIIC_BUFFER    =    Marshalled;
    g_uIIC_PT        =     0;
    g_uIIC_DATALEN    =    pInData->Count;

    g_pIICReg->IICCON |= (1<<7);        //    Ack generation Enable

    g_pIICReg->IICDS = pInData->SlaveAddress;

    DEBUGMSG(ZONE_INFO,(TEXT("[IIC TX]Slave Address is 0x%02X\n"),pInData->SlaveAddress));

    g_pIICReg->IICSTAT = MTX_START;

    if(WaitForSingleObject(g_hTransferDone, TIMEOUT_MS_TX) == WAIT_TIMEOUT)
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("[IIC ERROR]TX Time out.\r\n")));
        retVal = FALSE;
    }
    hr = CeFreeAsynchronousBuffer((PVOID)Marshalled, MappedEmbedded, pInData->Count, ARG_I_PTR);
    hr = CeCloseCallerBuffer((PVOID)  MappedEmbedded, pInData->Data, pInData->Count, ARG_I_PTR);

//CleanUp:
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-HW_Write(0x%X)\r\n"),
               pOpenContext));
    return retVal;
}

//////////
// Function Name : WaitForReg
// Function Description : Wait for register value, or time out.
// Input :     DWORD dwRegAddress,     // address of register for check
//                UINT32 tMask,         // mask for check position
//                UINT32 tWaitForEqual,    // compare value.
//                DWORD dwTimeout            // time out (ms)
// Output : True (the value is set), False (Time out)
// Version : v0.5
BOOL
WaitForReg(
    PVOID pRegAddress,
    UINT32 tMask,
    UINT32 tWaitForEqual,
    DWORD dwTimeout
    )
{

    const DWORD dwStart = GetTickCount();

    UINT32 tValue;

    BOOL fRet = TRUE;
    DWORD dwIteration = 1;

    // Verify that reset has completed.
    do {
        tValue = *(volatile UINT32*)(pRegAddress);

        if ( (dwIteration % 16) == 0 ) {
            // Check time
            DWORD dwCurr = GetTickCount();

            // Unsigned arithmetic handles rollover.
            DWORD dwTotal = dwCurr - dwStart;

            if (dwTotal > dwTimeout) {
                // Timeout
                fRet = FALSE;
                DEBUGMSG(ZONE_WARN    , (_T("Timeout (%u ms) waiting for REGISTER & 0x%08x == 0x%08x\r\n"),
                    dwTimeout, tMask, tWaitForEqual));
                break;
            }
        }

        ++dwIteration;
    } while ((tValue & tMask) != tWaitForEqual);

    return fRet;
}

static DWORD
IIC_IST(
    LPVOID Context
    )
{
    static DWORD    dwTimeOut = INFINITE;
    PHW_INIT_INFO pInitContext = (PHW_INIT_INFO)Context;
    BOOL bDone = FALSE;
    DWORD    iicstat;

// RETAILMSG(1(TEXT("****IIC_IST**********TEST*****")));

    if ( !pInitContext )
    {
        return ERROR_INVALID_PARAMETER;
    }

    while(pInitContext->State == IIC_RUN)
    {
        DWORD dwWaitResult;

        dwWaitResult = WaitForSingleObject(g_hTransferEvent, dwTimeOut);
        if(pInitContext->State == IIC_FINISH) continue;        // when we destruct IIC thread.

        iicstat = g_pIICReg->IICSTAT;
        if (iicstat & ARBITRATION_FAILED)
        {
            DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: bus arbitration failed \r\n"),
                g_OwnerContext, g_uIIC_PT));
            RETAILMSG(1,(TEXT("I2C_IST[0x%x, %d]: bus arbitration failed \r\n"),
                g_OwnerContext, g_uIIC_PT));
        }

        if (iicstat & SLAVE_ADDRESS_MATCHED)
        {
            DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: slave address matches IICADD \r\n"),
                g_OwnerContext, g_uIIC_PT));
            RETAILMSG(1,(TEXT("I2C_IST[0x%x, %d]: slave address matches IICADD \r\n"),
                g_OwnerContext, g_uIIC_PT));
        }

        if (iicstat & SLAVE_ADDRESS_ZERO)
        {
            DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: received slave address 0x0 \r\n"),
                g_OwnerContext, g_uIIC_PT));
            RETAILMSG(1,(TEXT("I2C_IST[0x%x, %d]: received slave address 0x0 \r\n"),
                g_OwnerContext, g_uIIC_PT));
        }

        if (iicstat & ACK_NOT_RECEIVED)
        {
            DEBUGMSG(ZONE_ERROR,(TEXT("I2C_IST[0x%x, %d]: ACK NOT received \r\n"),
                g_OwnerContext, g_uIIC_PT));
//            RETAILMSG(1,(TEXT("I2C_IST[0x%x, %d]: ACK NOT received \r\n"),
//                g_OwnerContext, g_uIIC_PT));
        }

        switch( (iicstat>>6)&0x3)
        {
            case Slave_receive:
                break;

            case Slave_transmit:
                break;

            case Master_receive:
                if (g_uIIC_PT>0 && g_uIIC_PT <=g_uIIC_DATALEN)
                {
                    g_pcIIC_BUFFER[g_uIIC_PT-1] = g_pIICReg->IICDS;
                }
                g_uIIC_PT++;
                if (g_uIIC_PT==g_uIIC_DATALEN)
                {
                    g_pIICReg->IICCON &= ~(1<<7);
                }
                else if (g_uIIC_PT > g_uIIC_DATALEN)
                {
                    bDone = TRUE;
                    g_pIICReg->IICSTAT = MRX_STOP;
                }
                g_pIICReg->IICCON &= ~(1<<4);

                break;
            case Master_transmit:
                if (g_uIIC_PT<g_uIIC_DATALEN)
                {
                    g_pIICReg->IICDS = g_pcIIC_BUFFER[g_uIIC_PT];
                    DEBUGMSG(ZONE_IST,(TEXT("[IIC TX THREAD]g_pIICReg->IICDS is 0x%02X\n"),g_pIICReg->IICDS));
                }
                else
                {
                    bDone = TRUE;
                    g_pIICReg->IICSTAT = MTX_STOP;        //    Stop Master Tx condition, ACK flag clear
                }
                g_uIIC_PT++;
                g_pIICReg->IICCON &= ~(1<<4);
                break;
            default :
                break;
        }

        InterruptDone(g_IntrIIC);

        if (bDone)
        {
            DEBUGMSG(ZONE_INFO, (TEXT("SetEvent DONE\r\n")));
            bDone = FALSE;
            SetEvent(g_hTransferDone);
        }
    }

    return ERROR_SUCCESS;
}

如果build的话会报错。由此需要修改iic_pdd.h

2.iic_pdd.h修改后的代码如下:

/**************************************************************************************
*
*    Project Name : IIC Driver
*
*    Copyright 2006 by Samsung Electronics, Inc.
*    All rights reserved.
*
*    Project Description :
*        This software is PDD layer for IIC Samsung driver.

*--------------------------------------------------
*
*    File Name : iic_pdd.h

*    File Description : This file declare PDD functions for IIC driver.
*
*    Author : JeGeon.Jung
*    Dept. : AP Development Team
*    Created Date : 2007/06/12
*    Version : 0.1
*
*    History
*    - Created(JeGeon.Jung 2007/06/12)

*    Todo
*
*
*    Note
*
**************************************************************************************/
#ifndef __IIC_PDD_H__
#define __IIC_PDD_H__

#if __cplusplus
extern "C"
{
#endif

#include <iic.h>

#define DEFAULT_SLAVE_ADDRESS        0xc0
#define DEFAULT_INTERRUPT_ENABLE    1

// I2C Master Commands (IICSTAT)
#define M_IDLE          0x00    // Disable Rx/Tx
#define M_ACTIVE      0x10    // Enable Rx/Tx
#define MTX_START    0xF0    // Master Tx Start
#define MTX_STOP      0xD0    // Master Tx Stop
#define MRX_START    0xB0    // Master Rx Start
#define MRX_STOP      0x90    // Master Rx Stop

// I2C State (IICSTAT)
#define ARBITRATION_FAILED              0x08
#define SLAVE_ADDRESS_MATCHED      0x04
#define SLAVE_ADDRESS_ZERO             0x02
#define ACK_NOT_RECEIVED                  0x01

//        declare functions
BOOL         HW_Init         (PHW_INIT_INFO pInitContext);
VOID         HW_Deinit         (PHW_INIT_INFO pInitContext);
BOOL         HW_OpenFirst     (PHW_OPEN_INFO pOpenContext);
BOOL         HW_CloseLast     (PHW_OPEN_INFO pOpenContext);

BOOL         HW_Open             (PHW_OPEN_INFO pOpenContext);
BOOL         HW_Close        (PHW_OPEN_INFO pOpenContext);

BOOL        HW_PowerUp        (PHW_INIT_INFO pInitContext);
BOOL        HW_PowerDown    (PHW_INIT_INFO pInitContext);

VOID         HW_SetRegister     (PHW_OPEN_INFO pOpenContext);
VOID         HW_SetClock        (PHW_OPEN_INFO pOpenContext);

BOOL        HW_Read             (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData ,PIIC_IO_DESC pOutData);
BOOL        HW_Write        (PHW_OPEN_INFO pOpenContext, PIIC_IO_DESC pInData);

#if __cplusplus
}
#endif

#endif //    __IIC_PDD_H__

 

3.build ok ,下载,测试,OK。

先在0位置写0,1位置写1,2位置写2,如下图,成功。

6410操作24C02驱动bug批改及测试

 然后,再读回来。

6410操作24C02驱动bug批改及测试

4.疑问:不知道操作其他IIC器件是否有问题?