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

📄 i2cclass.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// Returns:  
//      None.
//
//-----------------------------------------------------------------------------

VOID I2CClass::Reset(void)
{
    OUTREG16(&pI2CReg->I2CR, 0x0);
    iResult = I2C_NO_ERROR;
}

//-----------------------------------------------------------------------------
//
// Function: I2CClass::GenerateStart
//
// This method performs generates an I2C START signal to a slave device.
//
// Parameters:
//      pI2CPkt
//          [in] Contains all the necessary information to transmit/
//          receive from the slave device
//          
// Returns:  
//      TRUE   Success
//      FALSE  Error or timeout.
//
//-----------------------------------------------------------------------------

BOOL I2CClass::GenerateStart(PI2C_PACKET pI2CPkt)
{
    UINT16 i2sr;
    BYTE bySlaveAddr;
    int intrRetry;

    int count;

    if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IIF), 
                 I2C_I2SR_IIF_LSH) == I2C_I2SR_IIF_PENDING)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("IIF still pend in GenerateStart\r\n")));
    }

    count =0;
    while (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IBB),
                    I2C_I2SR_IBB_LSH) == I2C_I2SR_IBB_BUSY)
    {
        // Intentional polling loop.
        Sleep(1);
        ++count;
        if ( count >1000 )
        {
            DEBUGMSG(ZONE_FUNCTION, (_T("Generate Start can't be done\r\n")));
            (*(pI2CPkt->lpiResult)) = I2C_ERR_STATEMENT_CORRUPT;
            return FALSE;
        }
    }

    // Grant Bus Master
    INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA),
             CSP_BITFVAL(I2C_I2CR_MSTA, I2C_I2CR_MSTA_MASTER));

    // Ensure the START operation is done
    count =0;
    while (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IBB),
                    I2C_I2SR_IBB_LSH) != I2C_I2SR_IBB_BUSY)
    {
        // Intentional polling loop.
        ++count;
        if ( count >1000 )
        {
            DEBUGMSG(ZONE_FUNCTION, (_T("Generate Start can't launch\r\n")));
            break;
        }
    }

    // Ensure the START operation is success
    if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IAL),
                 I2C_I2SR_IAL_LSH) == I2C_I2SR_IAL_LOST)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("IAL detect in GenerateStart\r\n")));
        (*(pI2CPkt->lpiResult)) = I2C_ERR_ARBITRATION_LOST;
        goto error_cleanup;
    }

    // Ensure the START operation is success
    if (EXTREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA),
                 I2C_I2CR_MSTA_LSH) != I2C_I2CR_MSTA_MASTER)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("Master mode set failure\r\n")));
        (*(pI2CPkt->lpiResult)) = I2C_ERR_STATEMENT_CORRUPT;
        goto error_cleanup;
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): ")
                             TEXT("Bus Master Granted!\r\n")));

    { 
        i2sr = INREG16(&pI2CReg->I2SR);
        OUTREG16(&pI2CReg->I2SR, i2sr);
    }

    OUTREG16(&pI2CReg->I2SR, 0);
    if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IIF), 
                 I2C_I2SR_IIF_LSH) == I2C_I2SR_IIF_PENDING)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("IIF can not reset in GenerateStart\r\n")));
        (*(pI2CPkt->lpiResult)) = I2C_ERR_STATEMENT_CORRUPT;
        goto error_cleanup;
    }

    // Transmit the slave address, then change to receive mode after
    // we complete the address cycle.
    INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MTX),
             CSP_BITFVAL(I2C_I2CR_MTX, I2C_I2CR_MTX_TRANSMIT));

    bySlaveAddr = (pI2CPkt->byAddr << 1) |
                  ((pI2CPkt->byRW == I2C_RW_READ) ? 1 : 0);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): ")
                             TEXT("To I2DR->0x%x (slave addr)\r\n"),
                             bySlaveAddr));

    bDispatchEvent = TRUE;
    OUTREG16(&pI2CReg->I2DR, bySlaveAddr);

    // Wait for interrupt event
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): ")
                             TEXT("Waiting for incoming interrupt! \r\n")));

    intrRetry=iIntrWaitTimeoutRetry;
WaitRetry:
    if (WaitForSingleObject(m_hI2CIntrEvent, iIntrWaitTimeout) == WAIT_TIMEOUT)
    {
        if (--intrRetry>0)
        {
            goto WaitRetry;
        }
        DEBUGMSG(ZONE_ERROR, (TEXT("I2CClass::ProcessPacket(): ")
                              TEXT("Timed out waiting for interrupt! ")
                              TEXT("Aborting I2C transfer.\r\n")));

        (*(pI2CPkt->lpiResult)) = I2C_ERR_TRANSFER_TIMEOUT;
        goto error_cleanup;
    }

    i2sr = INREG16(&pI2CReg->I2SR);

    bDispatchEvent = FALSE;
    OUTREG16(&pI2CReg->I2SR, 0);
    ResetEvent(m_hI2CIntrEvent);
    InterruptDone(dwSysIntr);

    if (CSP_BITFEXT(i2sr, I2C_I2SR_RXAK) == I2C_I2SR_RXAK_NO_ACK_DETECT)
    {
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::GenerateStart(): ")
                                 TEXT("No ACK, STOP issued!\r\n")));

        DEBUGMSG(ZONE_FUNCTION, (TEXT("Address cycle No ACKd\r\n")));

        (*(pI2CPkt->lpiResult)) = I2C_ERR_NO_ACK_ISSUED;
        goto error_cleanup;
    }   
        
    return TRUE;

error_cleanup:

    bDispatchEvent = FALSE;
    OUTREG16(&pI2CReg->I2SR, 0);

    // Capture Error for debug
    if ( CleanupPendingInterrupt() )
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("Warning: Event remain pending AFTER ADDRESS CYCLE done\r\n")));
    }

    // Send a STOP Signal
    if (EXTREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA),
                 I2C_I2CR_MSTA_LSH) == I2C_I2CR_MSTA_MASTER)
    {
        GenerateStop();
    }
    return FALSE;
}


//-----------------------------------------------------------------------------
//
// Function: I2CClass::GenerateRepeatedStart
//
// This method performs generates an I2C REPEATED START signal to a slave
// device.
//
// Parameters:
//      pI2CPkt
//          [in] Contains all the necessary information to transmit/
//          receive from the slave device
//      
// Returns:  
//      TRUE   Success.
//      FALSE  Error or timeout.
//
//-----------------------------------------------------------------------------

BOOL I2CClass::GenerateRepeatedStart(PI2C_PACKET pI2CPkt, BOOL bRSTACycleComplete)
{
    BYTE bySlaveAddr;
    UINT16 i2sr;
    int intrRetry;

    // Set the repeated start bit in the I2C CR.
    if (!bRSTACycleComplete)
    {
        INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_RSTA),
                 CSP_BITFVAL(I2C_I2CR_RSTA, I2C_I2CR_RSTA_GENERATE));

        // Switch to Transmit Mode
        INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MTX), CSP_BITFVAL(I2C_I2CR_MTX, I2C_I2CR_MTX_TRANSMIT));
    }

    // Temporary fix related to Repeated Start. Delay after repeated start
    // for 1 PAT_REF_CLK period.
    StallExecution(3);

    // Ensure the START operation is success
    if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IAL),
                 I2C_I2SR_IAL_LSH) == I2C_I2SR_IAL_LOST)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("IAL detect in GenerateRepeatedStart\r\n")));
       (*(pI2CPkt->lpiResult)) = I2C_ERR_ARBITRATION_LOST;
        goto error_cleanup;
    }

    // Ensure the START operation is success
    if (EXTREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA),
                 I2C_I2CR_MSTA_LSH) != I2C_I2CR_MSTA_MASTER)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("RepeatedStart: Master mode set failure\r\n")));
       (*(pI2CPkt->lpiResult)) = I2C_ERR_STATEMENT_CORRUPT;
        goto error_cleanup;
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): ")
                             TEXT("Bus Master Granted!\r\n")));

    { 
        i2sr = INREG16(&pI2CReg->I2SR);
        OUTREG16(&pI2CReg->I2SR, i2sr);
    }

    OUTREG16(&pI2CReg->I2SR, 0);
    if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IIF), 
                 I2C_I2SR_IIF_LSH) == I2C_I2SR_IIF_PENDING)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("IIF can not reset in GenerateStart\r\n")));
       (*(pI2CPkt->lpiResult)) = I2C_ERR_STATEMENT_CORRUPT;
        goto error_cleanup;
    }

    // Append read or write bit to 7 bit slave address.
    bySlaveAddr = (pI2CPkt->byAddr << 1) |
                  ((pI2CPkt->byRW == I2C_RW_READ) ? 1 : 0);

    bDispatchEvent = TRUE;
    OUTREG16(&pI2CReg->I2SR, 0);
    OUTREG16(&pI2CReg->I2DR, bySlaveAddr);

    // Wait for interrupt event
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): ")
                             TEXT("Waiting for incoming interrupt! \r\n")));

    intrRetry=iIntrWaitTimeoutRetry;
WaitRetry:
    if (WaitForSingleObject(m_hI2CIntrEvent, iIntrWaitTimeout) == WAIT_TIMEOUT)
    {
        if (--intrRetry>0)
        {
            goto WaitRetry;
        }
        DEBUGMSG(ZONE_ERROR, (TEXT("I2CClass::ProcessPacket(): ")
                              TEXT("Timed out waiting for interrupt! ")
                              TEXT("Aborting I2C transfer.\r\n")));

       (*(pI2CPkt->lpiResult)) = I2C_ERR_TRANSFER_TIMEOUT;
        goto  error_cleanup;
    }

    i2sr = INREG16(&pI2CReg->I2SR);

    bDispatchEvent = FALSE;
    OUTREG16(&pI2CReg->I2SR, 0);
    ResetEvent(m_hI2CIntrEvent);
    InterruptDone(dwSysIntr);

    if (CSP_BITFEXT(i2sr, I2C_I2SR_RXAK) == I2C_I2SR_RXAK_NO_ACK_DETECT)
    {
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::GenerateStart(): ")
                                 TEXT("No ACK, STOP issued!\r\n")));

        (*(pI2CPkt->lpiResult)) = I2C_ERR_NO_ACK_ISSUED;
        goto error_cleanup;
    }   

    return TRUE;

error_cleanup:

    bDispatchEvent = FALSE;
    OUTREG16(&pI2CReg->I2SR, 0);

    // Capture Error for debug
    if ( CleanupPendingInterrupt() )
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("Warning: Event remain pending AFTER ADDRESS CYCLE done\r\n")));
    }

    // Send a STOP Signal
    if (EXTREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA),
                 I2C_I2CR_MSTA_LSH) == I2C_I2CR_MSTA_MASTER)
    {
        GenerateStop();
    }
    return FALSE;
}


//-----------------------------------------------------------------------------
//
// Function: I2CClass::GenerateStop
//
// This method generates a stop bit on the I2C bus
//
// Parameters:
//      None.
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
VOID I2CClass::GenerateStop()
{
    int count;

    if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IBB),
                 I2C_I2SR_IBB_LSH) != I2C_I2SR_IBB_BUSY)
        return;

    if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IAL),
                 I2C_I2SR_IAL_LSH) == I2C_I2SR_IAL_LOST)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("IAL detect in GenerateStop\r\n")));
    }

    if (EXTREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA),
                 I2C_I2CR_MSTA_LSH) == I2C_I2CR_MSTA_SLAVE)
    {
        DEBUGMSG(ZONE_FUNCTION, (_T("MSTA not set detect in GenerateStop\r\n")));
    }

    INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA),
             CSP_BITFVAL(I2C_I2CR_MSTA, I2C_I2CR_MSTA_SLAVE));

    // Wait for the stop condition to clear...
    count =0;
    while (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IBB),
                    I2C_I2SR_IBB_LSH) == I2C_I2SR_IBB_BUSY)
    {
        // Intentional polling loop.
        ++count;
        if( count >1000 ) {
            DEBUGMSG(ZONE_FUNCTION, (_T("GenerateStop not complete\r\n")));
            DEBUGMSG(ZONE_FUNCTION, (_T("SR=%02x, CR=%02x\r\n"),INREG16(&pI2CReg->I2SR),INREG16(&pI2CReg->I2CR)));
            break;
        }
    }
}

⌨️ 快捷键说明

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