📄 cspiclass.cpp
字号:
//------------------------------------------------------------------------------
//
// Function: CspiProcessQueue
//
// This function is the entry point for a thread that will be created during
// CSPI driver initialization and remain resident to process packet exchange
// requests from client devices.
//
// Parameters:
// lpParameter
// [in] Pointer to a single 32-bit parameter value passed to the
// thread during creation. Currently not used.
//
// Returns:
// Returns TRUE.
//
//------------------------------------------------------------------------------
DWORD WINAPI cspiClass::CspiProcessQueue(LPVOID lpParameter)
{
PCSPI_XCH_LIST_ENTRY_T pXchListEntry;
cspiClass * pCspi = (cspiClass *)lpParameter;
DEBUGMSG(ZONE_THREAD, (TEXT("CspiProcessQueue: lpParameter=0x%x\r\n"),lpParameter));
SetProcPermissions(0xFFFFFFFF);
// Until queue processing thread termination requested
while (!pCspi->m_bTerminate) {
// While our list of unprocessed queues has not been exhausted
while (!IsListEmpty(&pCspi->m_ListHead)) {
// Wrap linked list remove operation in critical section to
// serialize accesses with CSPI_IOCTL_EXCHANGE
EnterCriticalSection(&pCspi->m_cspiCs);
// Get next list entry
pXchListEntry = (PCSPI_XCH_LIST_ENTRY_T)RemoveHeadList(&pCspi->m_ListHead);
LeaveCriticalSection(&pCspi->m_cspiCs);
// Check if mapping failed
if (pXchListEntry == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("CspiProcessQueue: MapCallerPtr failed!\r\n")));
}
// Exchange packet mapped to our space
else {
// Wrap the exchange in critical section to
// serialize accesses with CSPI_IOCTL_EXCHANGE
EnterCriticalSection(&pCspi->m_cspiDataXchCs);
// Do the exchange and update the exchange count
pXchListEntry->xchPkt.xchCnt = pCspi->CspiDataExchange(&pXchListEntry->xchPkt);
LeaveCriticalSection(&pCspi->m_cspiDataXchCs);
// Signal that new data available in Rx message queue
if (!SetEvent(pXchListEntry->xchPkt.xchEvent))
DEBUGMSG(ZONE_ERROR, (TEXT("CspiProcessQueue: SetEvent failed\r\n")));
}
// Free memory allocated to list entry
HeapFree(pCspi->m_hHeap, 0, pXchListEntry);
} // while (!IsListEmpty(&m_ListHead))
// wait for next list entry to arrive
WaitForSingleObject(pCspi->m_hEnQEvent, INFINITE);
} // while (!m_bTerminate)
pCspi->m_hThread = NULL;
DEBUGMSG(ZONE_THREAD, (TEXT("CspiProcessQueue -\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: CspiDataExchange
//
// Exchanges CSPI data in Master mode.
//
// Parameters:
// pXchPkt
// [in] Points to exchange packet information.
//
// Returns:
// Returns the number of data exchanges that completed successfully.
//
//------------------------------------------------------------------------------
UINT32 cspiClass::CspiDataExchange(PCSPI_XCH_PKT_T pXchPkt)
{
PCSPI_BUSCONFIG_T pBusCnfg = pXchPkt->pBusCnfg;
LPVOID pTxBuf = pXchPkt->pTxBuf;
LPVOID pRxBuf = pXchPkt->pRxBuf;
UINT32 xchTxCnt = 0;
UINT32 xchRxCnt = 0;
volatile UINT32 tmp;
BOOL bXchDone = FALSE;
UINT32 (*pfnTxBufRd)(LPVOID);
void (*pfnRxBufWrt)(LPVOID, UINT32);
UINT8 bufIncr;
DEBUGMSG(ZONE_THREAD, (TEXT("CspiDataExchange: &m_pCSPI=0x%x\r\n"), &m_pCSPI));
// Check all translated pointers
if ((pBusCnfg == NULL) || (pTxBuf == NULL) || (pRxBuf == NULL))
return 0;
// Disable all interrupts
CLRREG32(&m_pCSPI->INT, 0x0003FE00);
// Set client CSPI bus configuration based
// default EN = disabled
// default MODE = master
// default XCH = idle
OUTREG32(&m_pCSPI->CONTROLREG,
CSP_BITFVAL(CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_DISABLE) |
CSP_BITFVAL(CSPI_CONTROLREG_MODE, CSPI_CONTROLREG_MODE_MASTER) |
CSP_BITFVAL(CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_IDLE) |
CSP_BITFVAL(CSPI_CONTROLREG_CS, pBusCnfg->chipselect) |
CSP_BITFVAL(CSPI_CONTROLREG_DATARATE, BSPCSPICalculateDivRate(pBusCnfg->freq)) |
CSP_BITFVAL(CSPI_CONTROLREG_SSPOL, pBusCnfg->sspol) |
CSP_BITFVAL(CSPI_CONTROLREG_SSCTL, pBusCnfg->ssctl) |
CSP_BITFVAL(CSPI_CONTROLREG_POL, pBusCnfg->pol) |
CSP_BITFVAL(CSPI_CONTROLREG_PHA, pBusCnfg->pha) |
CSP_BITFVAL(CSPI_CONTROLREG_BITCOUNT, pBusCnfg->bitcount) |
CSP_BITFVAL(CSPI_CONTROLREG_DRCTL, pBusCnfg->drctl));
// Select access funtions based on exchange bit width
//
// Bitcount Tx/Rx Buffer Access Width
// -------- -------------------------
// 1 - 8 UINT8 (unsigned 8-bit)
// 9 - 16 UINT16 (unsigned 16-bit)
// 17 - 32 UINT32 (unsigned 32-bit)
//
if ((pBusCnfg->bitcount >= 1) && (pBusCnfg->bitcount <= 8)) {
// 8-bit access width
pfnTxBufRd = CspiBufRd8;
pfnRxBufWrt = CspiBufWrt8;
bufIncr = sizeof(UINT8);
} else if ((pBusCnfg->bitcount >= 9) && (pBusCnfg->bitcount <= 16)) {
// 16-bit access width
pfnTxBufRd = CspiBufRd16;
pfnRxBufWrt = CspiBufWrt16;
bufIncr = sizeof(UINT16);
} else if ((pBusCnfg->bitcount >= 17) && (pBusCnfg->bitcount <= 32)) {
// 32-bit access width
pfnTxBufRd = CspiBufRd32;
pfnRxBufWrt = CspiBufWrt32;
bufIncr = sizeof(UINT32);
} else {
// Unsupported access width
DEBUGMSG(ZONE_WARN, (TEXT("CspiMasterDataExchange: unsupported bitcount!\r\n")));
return 0;
}
// Enable the clock gating
BSPCSPIEnableClock(m_nIndex, TRUE);
// Enable the CSPI
INSREG32BF(&m_pCSPI->CONTROLREG, CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_ENABLE);
// Until we are done with requested transfers
while (!bXchDone) {
// Load Tx FIFO until full, or until we run out of data
while ((!(INREG32(&m_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_TF)))
&& (xchTxCnt < pXchPkt->xchCnt)) {
// Put next Tx data into CSPI FIFO
OUTREG32(&m_pCSPI->TXDATA, pfnTxBufRd(pTxBuf));
// Increment Tx Buffer to next data point
pTxBuf = (LPVOID) ((UINT) pTxBuf + bufIncr);
// Increment Tx exchange counter
xchTxCnt++;
}
// Start exchange
INSREG32BF(&m_pCSPI->CONTROLREG, CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_EN);
if (xchTxCnt == pXchPkt->xchCnt) {
// If we completed requested transfers, then polling or enable
// interrupt for transfer completed
if (m_bUsePolling) {
// Wait until transaction is complete
while (!(INREG32(&m_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_TSHFE)));
} else {
INSREG32BF(&m_pCSPI->INT, CSPI_INT_TSHFEEN, CSPI_INT_TSHFEEN_ENABLE);
}
// Set flag to indicate requested exchange done
bXchDone = TRUE;
} else {
// Otherwise we need to wait until FIFO has more room, so
// we enable interrupt for Rx FIFO half-full (RHEN) to
// ensure we can read out data that arrived during exchange
if (m_bUsePolling) {
// Wait until RH
while (!(INREG32(&m_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_RH)));
} else {
INSREG32BF(&m_pCSPI->INT, CSPI_INT_RHEN, CSPI_INT_RHEN_ENABLE);
}
}
while (xchRxCnt < xchTxCnt) {
// Wait for requested transfer interrupt
WaitForSingleObject(m_hIntrEvent, INFINITE);
// Disable all interrupts
CLRREG32(&m_pCSPI->INT, 0x0003FE00);
// Acknowledge transfer complete (w1c)
OUTREG32(&m_pCSPI->INT, CSP_BITFMASK(CSPI_INT_TSHFEEN));
// While there is data in Rx FIFO and we have buffer space
while ((INREG32(&m_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_RR))
&& (xchRxCnt < pXchPkt->xchCnt)) {
tmp = INREG32(&m_pCSPI->RXDATA);
// If receive data is not to be discarded
if (pRxBuf != NULL) {
// Get next Rx data from CSPI FIFO
pfnRxBufWrt(pRxBuf, tmp);
// Increment Rx Buffer to next data point
pRxBuf = (LPVOID) ((UINT) pRxBuf + bufIncr);
}
// else receive data will be discarded
// Increment Rx exchange counter
xchRxCnt++;
}
// Signal that interrupt has been handled
InterruptDone(m_dwSysIntr);
// If Rx has not caught up to Tx, keep waiting until remaining
// data arrives
if (xchRxCnt < xchTxCnt) {
if (m_bUsePolling) {
// Disable all CSPI interrupts
CLRREG32(&m_pCSPI->INT, 0x0003FE00);
} else {
// Enable Rx FIFO ready interrupt (RREN)
INSREG32BF(&m_pCSPI->INT, CSPI_INT_RREN, CSPI_INT_RREN_ENABLE);
}
}
} // while (xchRxCnt < xchTxCnt)
} // while(!bXchDone)
#if 0
// Dump out what we just transmitted and received
pTxBuf = pXchPkt->pTxBuf;
pRxBuf = pXchPkt->pRxBuf;
for (xchTxCnt = 0; xchTxCnt < xchRxCnt; xchTxCnt++) {
DEBUGMSG(ZONE_THREAD, (TEXT("TXDATA[%d] = 0x%x\r\n"), xchTxCnt, pfnTxBufRd(pTxBuf)));
pTxBuf = (LPVOID) ((UINT) pTxBuf + bufIncr);
}
for (xchTxCnt = 0; xchTxCnt < xchRxCnt; xchTxCnt++) {
DEBUGMSG(ZONE_THREAD, (TEXT("RXDATA[%d] = 0x%x\r\n"), xchTxCnt, pfnTxBufRd(pRxBuf)));
pRxBuf = (LPVOID) ((UINT) pRxBuf + bufIncr);
}
#endif
// Disable the clock gating
BSPCSPIEnableClock(m_nIndex, FALSE);
DEBUGMSG(ZONE_THREAD, (TEXT("CspiDataExchange -\r\n")));
return xchRxCnt;
}
//------------------------------------------------------------------------------
//
// Function: CspiBufRd8
//
// This function is used to access a buffer as an array of 8-bit (UINT8)
// values and read data from the specified location.
//
// Parameters:
// pBuf
// [in] Pointer to buffer from which data will be read.
//
// Returns:
// Returns data pointed to by specified buffer, promoted to UINT32.
//
//------------------------------------------------------------------------------
UINT32 cspiClass::CspiBufRd8(LPVOID pBuf)
{
UINT8 *p;
p = (UINT8 *) pBuf;
return *p;
}
//------------------------------------------------------------------------------
//
// Function: CspiBufRd16
//
// This function is used to access a buffer as an array of 16-bit (UINT16)
// values and read data from the specified location.
//
// Parameters:
// pBuf
// [in] Pointer to buffer from which data will be read.
//
// Returns:
// Returns data pointed to by specified buffer, promoted to UINT32.
//
//------------------------------------------------------------------------------
UINT32 cspiClass::CspiBufRd16(LPVOID pBuf)
{
UINT16 *p;
p = (UINT16 *) pBuf;
return *p;
}
//------------------------------------------------------------------------------
//
// Function: CspiBufRd32
//
// This function is used to access a buffer as an array of 32-bit (UINT32)
// values and read data from the specified location.
//
// Parameters:
// pBuf
// [in] Pointer to buffer from which data will be read.
//
// Returns:
// Returns data pointed to by specified buffer.
//
//------------------------------------------------------------------------------
UINT32 cspiClass::CspiBufRd32(LPVOID pBuf)
{
UINT32 *p;
p = (UINT32 *) pBuf;
return *p;
}
//------------------------------------------------------------------------------
//
// Function: CspiBufWrt8
//
// This function is used to access a buffer as an array of 8-bit (UINT8)
// values and writes data to the specified buffer location.
//
// Parameters:
// pBuf
// [in] Pointer to buffer to which data will be written.
//
// data
// [in] Data to be written demoted to UINT8.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void cspiClass::CspiBufWrt8(LPVOID pBuf, UINT32 data)
{
UINT8 *p;
p = (UINT8 *) pBuf;
*p = (UINT8) data;
}
//------------------------------------------------------------------------------
//
// Function: CspiBufWrt16
//
// This function is used to access a buffer as an array of 16-bit (UINT16)
// values and writes data to the specified buffer location.
//
// Parameters:
// pBuf
// [in] Pointer to buffer to which data will be written.
//
// data
// [in] Data to be written demoted to UINT16.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void cspiClass::CspiBufWrt16(LPVOID pBuf, UINT32 data)
{
UINT16 *p;
p = (UINT16 *) pBuf;
*p = (UINT16) data;
}
//------------------------------------------------------------------------------
//
// Function: CspiBufWrt32
//
// This function is used to access a buffer as an array of 32-bit (UINT32)
// values and writes data to the specified buffer location.
//
// Parameters:
// pBuf
// [in] Pointer to buffer to which data will be written.
//
// data
// [in] Data to be written.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void cspiClass::CspiBufWrt32(LPVOID pBuf, UINT32 data)
{
UINT32 *p;
p = (UINT32 *) pBuf;
*p = data;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -