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

📄 i2cclass.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Send STOP...this is the last packet read. \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;
            }
        }

        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Read next byte! \r\n")));
        (*pReadBufPtr) = (BYTE) INREG16(&pI2CReg->I2DR);
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Byte read: %x \r\n"), *pReadBufPtr));
        ++pReadBufPtr;

        InterruptDone(dwSysIntr);
    }

    return TRUE;
}

//-----------------------------------------------------------------------------
//
// Function: I2CClass::ProcessPackets
//
// This is the main engine that transmits or receives data from I2C Bus
// Interface. This engine implements the complete I2C Bus Protocol which allows
// the calling process to interact with all I2C-compliant slave device. This
// method has built-in mechanism to prevent concurrent execution.
//
// Parameters:
//      pPacket 
//          [in] Contains all the necessary information to transmit/
//          receive from the slave device.
//
//      dwNumPackets
//          [in] Number of packets to be processed.
//
// Returns:  
//      None.
//
//-----------------------------------------------------------------------------
BOOL I2CClass::ProcessPackets(I2C_PACKET packets[], INT32 numPackets)
{
    // Must gain ownership to bus lock mutex
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): + \r\n")));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Waiting for Bus Lock CS \r\n")));
    EnterCriticalSection(&gcsI2CBusLock);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Acquired Bus Lock CS! \r\n")));

    // Flag to signal if address cycle just completed
    BOOL bAddrCycleComplete;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket():BSPI2CEnableClock(): Enabling I2C Clock! \r\n")));

    // Enabling I2C Clock
    if (!BSPI2CEnableClock(m_iModuleIndex, TRUE))
    {
        DEBUGMSG(ZONE_FUNCTION | ZONE_ERROR, (TEXT("I2CClass::ProcessPacket():BSPI2CEnableClock(): I2C Clock cannot be enabled! \r\n")));
        return FALSE;
    }

    // Reset I2CR
    OUTREG16(&pI2CReg->I2CR, 0x0);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Resetting I2CR \r\n")));

    // Try resetting I2DR = 0x0
    OUTREG16(&pI2CReg->I2DR, 0x0);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Resetting I2DR \r\n")));

    // Configure data sampling rate
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Trying to set IFDR->0x%x! \r\n"), wLastClkRate));
    OUTREG16(&pI2CReg->IFDR, CSP_BITFVAL(I2C_IFDR_IC, wLastClkRate));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Set IFDR->0x%x! \r\n"), INREG16(&pI2CReg->IFDR)));

    // Configure slave address
    OUTREG16(&pI2CReg->IADR, CSP_BITFVAL(I2C_IADR_ADR, byLastSelfAddr));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Configure Self Address->0x%x \r\n"), INREG16(&pI2CReg->IADR)));

    // Enable I2C
    INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_IEN), CSP_BITFVAL(I2C_I2CR_IEN, I2C_I2CR_IEN_ENABLE));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Enable I2C \r\n")));

    // Enable I2C Interrupt
    INSREG16(&pI2CReg->I2CR, CSP_BITFMASK(I2C_I2CR_IIEN), CSP_BITFVAL(I2C_I2CR_IIEN, I2C_I2CR_IIEN_ENABLE));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Enable I2C Interrupt \r\n")));

    // For each I2C packet, transfer data as specified
    for (int i = 0; i < numPackets; i++)
    {
        bAddrCycleComplete = FALSE;

        // Initialize Tx/Rx buffer navigator
        DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Setting up Tx/Rx Buffer Navigator \r\n")));
        PBYTE pbyBufPtr = packets[i].pbyBuf;
        PBYTE pbyBufEnd = pbyBufPtr + packets[i].wLen;

        // Send a START signal if this is our first packet
        if (i == 0)
        {
            DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket():Issuing START command.\r\n")));
            GenerateStart(&packets[i]);

            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.
                *(packets[i].lpiResult) = I2C_ERR_ARBITRATION_LOST;

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

            bAddrCycleComplete = TRUE;
        }
        // Send a REPEATED START signal if the address
        // changed or the transfer direction changed.
        else if ((packets[i].byAddr != packets[i - 1].byAddr) ||
                   (packets[i].byRW != packets[i - 1].byRW))
        {
            DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket():Issuing REPEATED START command.\r\n")));
            GenerateRepeatedStart(&packets[i]);

            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->I2SR, CSP_BITFMASK(I2C_I2SR_IAL), I2C_I2SR_IAL_NOT_LOST);
                return FALSE;
            }

            if (EXTREG16BF(&pI2CReg->I2SR, I2C_I2SR_IAL))
            {
                // Arbitration lost.  An error has occurred, likely due to a bad
                // slave I2C address.
                *(packets[i].lpiResult) = I2C_ERR_ARBITRATION_LOST;

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

            bAddrCycleComplete = TRUE;
        }

        // Is I2C in master mode?
        if (byLastMode == I2C_MASTER_MODE)
        {

            DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): I2C In Master Mode! \r\n")));
            // I2C Transmitting?
            if (packets[i].byRW == I2C_RW_WRITE)
            {
                if (!WritePacket(&packets[i], (i + 1 == numPackets)))
                {
                    *(packets[i].lpiResult) = I2C_ERR_TRANSFER_TIMEOUT;
                    return FALSE;
                }
            }
            // I2C Receiving?
            else
            {
                if (!ReadPacket(&packets[i], (i + 1 == numPackets), bAddrCycleComplete))
                {
                    *(packets[i].lpiResult) = I2C_ERR_TRANSFER_TIMEOUT;
                    return FALSE;
                }
            }
                
        }
        else
        {
            // TODO: Is slave mode support needed?
        }
    }

    // Disable I2C Module
    OUTREG16(&pI2CReg->I2CR, 0);

    // Disable I2C Clock
    DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket(): Disabling I2C Clock! \r\n")));                

    BSPI2CEnableClock(m_iModuleIndex, FALSE);

    // On completion, release bus lock mutex
    LeaveCriticalSection(&gcsI2CBusLock);

    // Return success
    return TRUE;
}


//------------------------------------------------------------------------------
//
// Function: I2CIST
//
// This function is the IPU IST thread.
//
// Parameters:
//      None
//
// Returns:
//      None
//
//-----------------------------------------------------------------------------
void I2CClass::I2CIST(LPVOID lpParameter)
{
    I2CClass *pI2C = (I2CClass *)lpParameter;

    pI2C->I2CInterruptHandler(INFINITE);

    return;
}



//-----------------------------------------------------------------------------
//
// Function: I2CInterruptHandler
//
// This function is the interrupt handler for the I2C.
// It waits for an I2C interrupt, and signals
// the event to the driver.  This additional layer of 
// event signalling is required to prevent priority inversion bugs.
//
// Parameters:
//      timeout
//          [in] Timeout value while waiting for EOF interrupt.
//
// Returns:
//      None
//
//-----------------------------------------------------------------------------
void I2CClass::I2CInterruptHandler(UINT32 timeout)
{
    // loop here
    while(TRUE)
    {
        DEBUGMSG (ZONE_FUNCTION, (TEXT("%s: In the loop\r\n"), __WFUNCTION__));

        if (WaitForSingleObject(hInterrupted, timeout) == WAIT_OBJECT_0)
        {
            DEBUGMSG (ZONE_FUNCTION, (TEXT("%s: Interrupt received\r\n"), __WFUNCTION__));

            SetEvent(m_hI2CIntrEvent);

            // Kernel call to unmask the interrupt so that it can be signalled again
//            InterruptDone(dwSysIntr);
        }
        else
        {
            DEBUGMSG (ZONE_ERROR, (TEXT("%s: Time out\r\n"), __WFUNCTION__));
        }

    }
    return;
}

⌨️ 快捷键说明

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