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

📄 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 页
字号:

    // Must gain ownership to bus lock mutex
    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")));

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

    if (!bSlaveInUse)
    {
        // Enabling I2C Clock
        if (!BSPI2CEnableClock(m_iModuleIndex, TRUE))
        {
            DEBUGMSG(ZONE_FUNCTION | ZONE_ERROR, (TEXT("I2CClass::ProcessPacket():BSPI2CEnableClock(): I2C Clock cannot be enabled! \r\n")));
            retVal = FALSE;
            goto __exit;
        }
    }
    else 
    {
        UINT16 i2sr;
        i2sr = INREG16(&pI2CReg->I2SR);
        while ( /*(CSP_BITFEXT(i2sr, I2C_I2SR_ICF)==I2C_I2SR_ICF_IN_PROGRESS)
                ||*/(CSP_BITFEXT(i2sr, I2C_I2SR_IBB) == I2C_I2SR_IBB_BUSY) )
        {
            // Intentional polling loop.
            Sleep(0);
            i2sr = INREG16(&pI2CReg->I2SR);
        }
        byInUseSlaveAddr = (BYTE)INREG16(&pI2CReg->IADR);
    }


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

    // Well, if every thing is ok, and all error exits clean their pending interrupt
    // this shall never need. After all the check adds cost to every i2c xfer call.
    // Actually, only failure xfer need do it.

    // if ( CleanupPendingInterrupt() )
    // {
    //     DEBUGMSG(ZONE_FUNCTION, (_T("Warning: There is Pending interrupt before process packets\r\n")));
    // }

    HANDLE hCurrentThread = GetCurrentThread ();
    DWORD dwOrigThreadQuant = CeGetThreadQuantum ( hCurrentThread);
    CeSetThreadQuantum ( hCurrentThread, dwOrigThreadQuant * 3 );

    DWORD dwOrigThreadPrior = CeGetThreadPriority( hCurrentThread );
    CeSetThreadPriority(hCurrentThread, CE_THREAD_PRIO_256_TIME_CRITICAL);

    // For each I2C packet, transfer data as specified
    bRSTACycleComplete = FALSE;
    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")));

        *(packets[i].lpiResult) = I2C_ERR_STATEMENT_CORRUPT;

        // Send a START signal if this is our first packet
        if (i == 0)
        {
            DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket():Issuing START command.\r\n")));
            if (!GenerateStart(&packets[i]))
            {
                retVal = FALSE;
                goto __exit;
            }
            bAddrCycleComplete = TRUE;
        }
        // Send a REPEATED START signal if the address
        // changed or the transfer direction changed.
        else 
        {
            DEBUGMSG(ZONE_FUNCTION, (TEXT("I2CClass::ProcessPacket():Issuing REPEATED START command.\r\n")));
            if (!GenerateRepeatedStart(&packets[i], bRSTACycleComplete))
            {
                retVal = FALSE;
                goto __exit;
            }

            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)))
                {
                    retVal = FALSE;
                    goto __exit;
                }
                bRSTACycleComplete = FALSE;
            }
            // I2C Receiving?
            else
            {
                if (!ReadPacket(&packets[i], 
                                (i + 1 == numPackets), 
                                bAddrCycleComplete,
                                &bRSTACycleComplete))
                {
                    retVal = FALSE;
                    goto __exit;
                }
            }

            *(packets[i].lpiResult) = I2C_NO_ERROR;
        }
    }
    
__exit:
    CeSetThreadQuantum ( hCurrentThread, dwOrigThreadQuant );
    CeSetThreadPriority( hCurrentThread, dwOrigThreadPrior);

    if (!bSlaveInUse)
    {
        if (EXTREG16(&pI2CReg->I2SR, CSP_BITFMASK(I2C_I2SR_IIF), 
                     I2C_I2SR_IIF_LSH) == I2C_I2SR_IIF_PENDING)
        {
            DEBUGMSG(ZONE_FUNCTION, (_T("IIF dose not reset in ProcessPkt\r\n")));
        }

        // 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);
    }
    else 
    {
        UINT16 i2cr;

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

        // Init I2CR
        i2cr = CSP_BITFVAL(I2C_I2CR_IEN, 1);
        OUTREG16(&pI2CReg->I2CR, i2cr);
        i2cr = CSP_BITFVAL(I2C_I2CR_IEN, 1)|CSP_BITFVAL(I2C_I2CR_IIEN, 1);
        OUTREG16(&pI2CReg->I2CR, i2cr);
        OUTREG16(&pI2CReg->I2SR, 0);
    }

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

    return retVal;
}


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

    pI2C->I2CInterruptHandler(INFINITE);

    // Should only ever get here with bTerminateISTThread == TRUE. Simply
    // returning here will gracefully terminate the IST handler thread.
    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)
{
    UINT16 i2sr;
    UINT16 i2cr;
    INT i;
    INT iIdleCount;

    // Loop here until signal to terminate the IST thread is received.

__loop:
    while(!bTerminateISTThread)
    {
        DEBUGMSG (ZONE_FUNCTION, (TEXT("%s: In the loop\r\n"), __WFUNCTION__));

        if (WaitForSingleObject(hInterrupted, timeout) == WAIT_OBJECT_0)
        {

            // Check if we woke up because of a terminate IST thread request.
            if (bTerminateISTThread)
            {
                break;
            }

            DEBUGMSG (ZONE_FUNCTION, (TEXT("%s: Interrupt received\r\n"), __WFUNCTION__));

            i2cr =INREG16(&pI2CReg->I2CR);
            i2sr= INREG16(&pI2CReg->I2SR);

            // if receive unexpected IIF
            //    we discard the data in I2DR
            //    and 
            //    give NO ACK signal to master
            //    and release SCL line
            if ((CSP_BITFEXT(i2cr, I2C_I2CR_MSTA)==I2C_I2CR_MSTA_SLAVE) 
                && (CSP_BITFEXT(i2sr, I2C_I2SR_IAAS)==I2C_I2SR_IAAS_NOT_ADDRESSED)
                && (CSP_BITFEXT(i2sr, I2C_I2SR_IAL)==I2C_I2SR_IAL_NOT_LOST)
                && (CSP_BITFEXT(i2sr, I2C_I2SR_IIF)==I2C_I2SR_IIF_PENDING))
            {
                CSP_BITFCLR(i2cr, I2C_I2CR_MTX);
                i2cr|=CSP_BITFVAL(I2C_I2CR_TXAK, 1);
                OUTREG16(&pI2CReg->I2CR, i2cr);
                INREG16(&pI2CReg->I2DR);
                CSP_BITFCLR(i2sr, I2C_I2SR_IAL);
                CSP_BITFCLR(i2sr, I2C_I2SR_IIF);
                OUTREG16(&pI2CReg->I2SR, i2sr);
                InterruptDone(dwSysIntr);
                continue;
            }


            if ((CSP_BITFEXT(i2cr, I2C_I2CR_MSTA)==I2C_I2CR_MSTA_SLAVE) 
                && (CSP_BITFEXT(i2sr, I2C_I2SR_IAAS)==I2C_I2SR_IAAS_ADDRESSED)
                && (CSP_BITFEXT(i2sr, I2C_I2SR_IIF)==I2C_I2SR_IIF_PENDING))
            {
                
                i2cr= INREG16(&pI2CReg->I2CR);
                CSP_BITFCLR(i2cr, I2C_I2CR_IIEN);
                OUTREG16(&pI2CReg->I2CR, i2cr);

                InterruptDone(dwSysIntr);

iaas_slave:
                // iaas_slave flag:
                // software can't get STOP/RESTART signal from i2c hardware
                // whenever we find IAAS is set, 
                // treat it as the slave is selected again
                while(CSP_BITFEXT(i2sr, I2C_I2SR_IIF)!=1)
                {
                    i2sr= INREG16(&pI2CReg->I2SR); 
                }

                i2cr= INREG16(&pI2CReg->I2CR);
                CSP_BITFCLR(i2sr, I2C_I2SR_IAL);
                CSP_BITFCLR(i2sr, I2C_I2SR_IIF);
                OUTREG16(&pI2CReg->I2SR, i2sr);

                if (CSP_BITFEXT(i2sr, I2C_I2SR_SRW)==I2C_I2SR_SRW_TRANSMIT)
                {
                    //  i2c is in slave transmit mode
                    if(pSBuf->iBufSize<=1)
                    {
                        i2cr|=CSP_BITFVAL(I2C_I2CR_MTX, 1);
                        i2cr|=CSP_BITFVAL(I2C_I2CR_TXAK, 1);
                        OUTREG16(&pI2CReg->I2CR, i2cr);
                        OUTREG16(&pI2CReg->I2DR, pSBuf->byBuf[0]);
                        iIdleCount=I2C_TRANSMIT_WAIT;
                        i2sr= INREG16(&pI2CReg->I2SR);
                        while (CSP_BITFEXT(i2sr, I2C_I2SR_IIF)!=1) 
                        {
                            --iIdleCount;
                            if( iIdleCount<=0 )
                            {
                                goto end_transmit;
                            }
                            i2sr= INREG16(&pI2CReg->I2SR);
                            if (CSP_BITFEXT(i2sr, I2C_I2SR_IAL)==1)
                            {
                                goto end_transmit;
                            }
                            if (CSP_BITFEXT(i2sr, I2C_I2SR_IBB)==0)
                            {
                                goto end_transmit;
                            }
                            if (CSP_BITFEXT(i2sr, I2C_I2SR_IAAS)==1)
                            {
                                goto iaas_slave;
                            }
                            i2cr= INREG16(&pI2CReg->I2CR);
                            if (CSP_BITFEXT(i2cr, I2C_I2CR_IIEN)==1)
                            {
                                // the interface is preempted by master mode
                                goto __loop;
                            }
                        }
                    }
                    else 
                    {
                        i2cr|=CSP_BITFVAL(I2C_I2CR_MTX, 1);
                        CSP_BITFCLR(i2cr, I2C_I2CR_TXAK);
                        OUTREG16(&pI2CReg->I2CR, i2cr);
                        for (i=0; i<pSBuf->iBufSize; ++i)
                        {
                           if (i>=pSBuf->iBufSize-1) 
                            {
                                i2cr|=CSP_BITFVAL(I2C_I2CR_TXAK, 1);
                                OUTREG16(&pI2CReg->I2CR, i2cr);
                            }
                            OUTREG16(&pI2CReg->I2DR, pSBuf->byBuf[i]);

                            i2sr= INREG16(&pI2CReg->I2SR);
                            iIdleCount=I2C_TRANSMIT_WAIT;
                            while (CSP_BITFEXT(i2sr, I2C_I2SR_IIF)!=1) 
                            {
                                --iIdleCount;
                                if( iIdleCount<=0 )
                                {
                                    goto end_transmit;
                                }
                                i2sr= INREG16(&pI2CReg->I2SR);
                                if (CSP_BITFEXT(i2sr, I2C_I2SR_IAL)==1)
                                {
                                    goto end_transmit;
                                }
                                if (CSP_BITFEXT(i2sr, I2C_I2SR_IBB)==0)
                                {
                                    goto end_transmit;
                                }
                                if (CSP_BITFEXT(i2sr, I2C_I2SR_IAAS)==1)
                                {
                                    goto iaas_slave;

⌨️ 快捷键说明

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