📄 i2cclass.cpp
字号:
// 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 + -