⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c6410_iic_lib.cpp

📁 6410BSP3
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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));

    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));

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-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)
{
    BOOL    retVal           = TRUE;        // Initialize to success
    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;
    }
    g_pcIIC_BUFFER    =    pOutData->Data;
    g_uIIC_PT        =    0;
    g_uIIC_DATALEN    =    pOutData->Count;

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

    g_pIICReg->IICDS = pInData->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;
    }

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)
{
    BOOL    retVal           = TRUE;        // Initialize to success

    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;
    }

    g_pcIIC_BUFFER    =    pInData->Data;
    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;
    }

    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;
    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));
        }

        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));
        }

        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));
        }

        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)
            {
                bDone = FALSE;
                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)
            {
                bDone = FALSE;
                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;
        }

        InterruptDone(g_IntrIIC);

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

    return ERROR_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -