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