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

📄 i2cclass.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

    // Release Interrupt Occurrence Event -
    {   
        if (hInterrupted != NULL)
            CloseHandle(hInterrupted);

        DEBUGMSG(ZONE_DEINIT, (TEXT("I2CClass::~I2CClass: Release Interrupt Occurence Event \r\n")));
    }

    // Release I2C Register Base Mapped Virtual Memory -
    {
        if (pI2CReg != NULL)
            MmUnmapIoSpace((LPVOID) pI2CReg, sizeof(CSP_I2C_REG));

        DEBUGMSG(ZONE_DEINIT, (TEXT("I2CClass::~I2CClass: Release I2C Register Base Mapped Virtual Memory \r\n")));
    }

    DEBUGMSG(ZONE_DEINIT, (TEXT("I2CClass::~I2CClass -\r\n")));
}

//-----------------------------------------------------------------------------
//
// Function: I2CClass::Reset
//
// This method performs a software reset on I2C internal register (I2CR). It is
// important to take note that the fields of the I2CClass are not modified in
// any way.
//
// Parameters:
//  None.
//
// 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:  
//      None.
//
//-----------------------------------------------------------------------------

VOID I2CClass::GenerateStart(PI2C_PACKET pI2CPkt)
{
    BYTE bySlaveAddr;
    while (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IBB), I2C_I2SR_IBB_LSH) == I2C_I2SR_IBB_BUSY);

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

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

    // 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(): To I2DR->0x%x (slave addr)\r\n"), bySlaveAddr));
    OUTREG16(&pI2CReg->I2DR, bySlaveAddr);
}


//-----------------------------------------------------------------------------
//
// 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:  
//      None.
//
//-----------------------------------------------------------------------------

VOID I2CClass::GenerateRepeatedStart(PI2C_PACKET pI2CPkt)
{
    BYTE bySlaveAddr;

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

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

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

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


//-----------------------------------------------------------------------------
//
// Function: I2CClass::WritePacket
//
// This method performs a write operation with the data in one I2C_PACKET.
//
// Parameters:
//      pI2CPkt
//          [in] Contains all the necessary information to transmit/
//          receive from the slave device.
//
//      bLast
//          [in] Signifies if this is the last packet to be transmitted.
//
// Returns:  
//      None.
//
//-----------------------------------------------------------------------------
BOOL I2CClass::WritePacket(PI2C_PACKET pI2CPkt, BOOL bLast)
{
    PBYTE pWriteBufPtr = pI2CPkt->pbyBuf;

    // Set MTX to switch to transmit mode
    INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MTX), CSP_BITFVAL(I2C_I2CR_MTX, I2C_I2CR_MTX_TRANSMIT));

    for (int i = 0; i < pI2CPkt->wLen; i++)
    {
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Transmitting Next Byte: %x! \r\n"), *pWriteBufPtr));
        OUTREG16(&pI2CReg->I2DR, (*pWriteBufPtr));
        pWriteBufPtr++;

        InterruptDone(dwSysIntr);

        // Wait for interrupt event
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Waiting for incoming interrupt! \r\n")));
        if (WaitForSingleObject(m_hI2CIntrEvent, iIntrWaitTimeout) == WAIT_TIMEOUT)
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("I2CClass::ProcessPacket(): Timed out waiting for interrupt!  Aborting I2C transfer.\r\n")));

            // Send stop signal to abort
            INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA), CSP_BITFVAL(I2C_I2CR_MSTA, I2C_I2CR_MSTA_SLAVE));
            return FALSE;
        }

        if (EXTREG16BF(&pI2CReg->I2SR, I2C_I2SR_IAL))
        {
            // Arbitration lost.  An error has occurred, likely due to a bad
            // slave I2C address.

            // Clear IAL bit (we are already put into Stop)
            INSREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IAL), I2C_I2SR_IAL_NOT_LOST);
            return FALSE;
        }


        // Clear Interrupt Signal
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Clear Interrupt! \r\n")));
        INSREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IIF), CSP_BITFVAL(I2C_I2SR_IIF, 0));

        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Got Detect ACK? \r\n")));
        if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_RXAK), I2C_I2SR_RXAK_LSH) == I2C_I2SR_RXAK_NO_ACK_DETECT)
        {
           DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): No ACK, STOP issued! -\r\n")));
           // Send a STOP Signal
           INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA), CSP_BITFVAL(I2C_I2CR_MSTA, I2C_I2CR_MSTA_SLAVE));
            (*(pI2CPkt->lpiResult)) = I2C_ERR_NO_ACK_ISSUED;
           break;
        }   // if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_RXAK), I2C_I2SR_RXAK_LSH) == I2C_I2SR_RXAK_NO_ACK_DETECT)
    }
    if (bLast)
    {
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Send STOP...this is the last packet written. \r\n")));
        // Send STOP signal if this is the last packet to process
        INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA), CSP_BITFVAL(I2C_I2CR_MSTA, I2C_I2CR_MSTA_SLAVE));

        // Linux code also clears MTX as part of STOP
        INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MTX), CSP_BITFVAL(I2C_I2CR_MTX, I2C_I2CR_MTX_TRANSMIT));

        (*(pI2CPkt->lpiResult)) = I2C_NO_ERROR;
    }

    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: I2CClass::ReadPacket
//
// This method performs a read operation with the data in one I2C_PACKET.
//
// Parameters:
//      pI2CPkt
//          [in] Contains all the necessary information to transmit/
//          receive from the slave device.
//
//      bLast
//          [in] Signifies if this is the last packet to be transmitted.
//
//      bAddrCycleComplete
//          [in] Signifies that the slave address cycle was just completed.
//
// Returns:  
//      None.
//
//-----------------------------------------------------------------------------
BOOL I2CClass::ReadPacket(PI2C_PACKET pI2CPkt, BOOL bLast, BOOL bAddrCycleComplete)
{
    PBYTE pReadBufPtr = pI2CPkt->pbyBuf;

    // Switch to Receive Mode
    INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MTX), CSP_BITFVAL(I2C_I2CR_MTX, I2C_I2CR_MTX_RECEIVE));

    // Clear the TXAK bit to gen an ack when receiving only one byte.
    if (pI2CPkt->wLen == 1)
    {
        INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_TXAK), CSP_BITFVAL(I2C_I2CR_TXAK, I2C_I2CR_TXAK_NO_ACK_SEND));
    }
    else
    {
        INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_TXAK), CSP_BITFVAL(I2C_I2CR_TXAK, I2C_I2CR_TXAK_ACK_SEND));
    }

    if (bAddrCycleComplete)
    {
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Dummy read to trigger I2C Read operation.\r\n")));
        // Dummy read to trigger I2C Read operation
        INREG16(&pI2CReg->I2DR);

        // TODO: Needed?  If we remove, will this interfere with interrupt generation for following read op?
        InterruptDone(dwSysIntr);
    }

    for (int i = 0; i < pI2CPkt->wLen; i++)
    {

        // Wait for data transmission to complete.
        // Wait for interrupt event.
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Waiting for incoming interrupt! \r\n")));
        if (WaitForSingleObject(m_hI2CIntrEvent, iIntrWaitTimeout) == WAIT_TIMEOUT)
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("I2CClass::ProcessPacket(): Timed out waiting for interrupt!  Aborting I2C transfer.\r\n")));                // Send STOP signal if this is the last packet to process

            // Send stop signal to abort
            INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_MSTA), CSP_BITFVAL(I2C_I2CR_MSTA, I2C_I2CR_MSTA_SLAVE));
            return FALSE;
        }

        if (EXTREG16BF(&pI2CReg->I2SR, I2C_I2SR_IAL))
        {
            // Arbitration lost.  An error has occurred, likely due to a bad
            // slave I2C address.

            // Clear IAL bit (we are already put into Stop)
            INSREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IAL), I2C_I2SR_IAL_NOT_LOST);
            return FALSE;
        }

        // Clear Interrupt Signal
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Clear Interrupt! \r\n")));
        INSREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IIF), CSP_BITFVAL(I2C_I2SR_IIF, 0));

        // Do not generate an ACK for the last byte 
        if (i == (pI2CPkt->wLen - 2))
        {
            DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Change to No ACK for last byte. \r\n")));
            INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_TXAK), CSP_BITFVAL(I2C_I2CR_TXAK, I2C_I2CR_TXAK_NO_ACK_SEND));
        }
        else if (i == (pI2CPkt->wLen - 1))
        {
            if (bLast)
            {

⌨️ 快捷键说明

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