📄 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
OUTREG32(&m_pCSPI->INTREG, 0);
// set client CSPI bus configuration based
// default EN = disabled
// default MODE = master
// default XCH = idle
// default SMC = XCH bit controls master start transfer
OUTREG32(&m_pCSPI->CONREG,
CSP_BITFVAL(CSPI_CONREG_EN, CSPI_CONREG_EN_DISABLE) |
CSP_BITFVAL(CSPI_CONREG_MODE, CSPI_CONREG_MODE_MASTER) |
CSP_BITFVAL(CSPI_CONREG_XCH, CSPI_CONREG_XCH_IDLE) |
CSP_BITFVAL(CSPI_CONREG_SMC, CSPI_CONREG_SMC_XCH) |
CSP_BITFVAL(CSPI_CONREG_CHIPSELECT, pBusCnfg->chipselect) |
CSP_BITFVAL(CSPI_CONREG_DATARATE, BSPCSPICalculateDivRate(pBusCnfg->freq)) |
CSP_BITFVAL(CSPI_CONREG_SSPOL, pBusCnfg->sspol) |
CSP_BITFVAL(CSPI_CONREG_SSCTL, pBusCnfg->ssctl) |
CSP_BITFVAL(CSPI_CONREG_POL, pBusCnfg->pol) |
CSP_BITFVAL(CSPI_CONREG_PHA, pBusCnfg->pha) |
CSP_BITFVAL(CSPI_CONREG_BITCOUNT, pBusCnfg->bitcount) |
CSP_BITFVAL(CSPI_CONREG_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_Index,TRUE);
// enable the CSPI
INSREG32(&m_pCSPI->CONREG, CSP_BITFMASK(CSPI_CONREG_EN),
CSP_BITFVAL(CSPI_CONREG_EN, CSPI_CONREG_EN_ENABLE));
if (m_bUseDMA)
{
UINT32 WordCount = pXchPkt->xchCnt / 4;
if (WordCount) // pXchPkt->xchCnt is more than 4
{
m_nondmaTransferCount = pXchPkt->xchCnt % 4;
m_dmaTransferCount = WordCount * 4;
m_isDMADone = FALSE;
}
else
{
m_nondmaTransferCount = pXchPkt->xchCnt;
m_dmaTransferCount = 0;
}
// assert DMA request for half or empty
// irrespective of the condition,
// we need to enable the transmitter
// INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_THDEN),
// CSP_BITFVAL(CSPI_DMAREG_THDEN, CSPI_DMAREG_THDEN_ENABLE));
INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_TEDEN),
CSP_BITFVAL(CSPI_DMAREG_TEDEN, CSPI_DMAREG_TEDEN_ENABLE));
if (m_dmaTransferCount)
{
INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_RHDEN),
CSP_BITFVAL(CSPI_DMAREG_RHDEN, CSPI_DMAREG_RHDEN_ENABLE));
//INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_RFDEN),
// CSP_BITFVAL(CSPI_DMAREG_RFDEN, CSPI_DMAREG_RFDEN_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->STATREG) & CSP_BITFMASK(CSPI_STATREG_TF)))
&& (xchTxCnt < pXchPkt->xchCnt))
{
if (m_bUseDMA)
{
DDKSdmaClearBufDescStatus(m_dmaChanCspiTx,0);
DDKSdmaSetBufDesc(m_dmaChanCspiTx, 0,
DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP,
PhysDMABufferAddr.LowPart + CSPI_TXMT_OFFSET,
0, DDK_DMA_ACCESS_32BIT, pXchPkt->xchCnt * 4); // set the count in bytes.
MoveDMABuffer(pTxBuf, pXchPkt->xchCnt * 4, FALSE); // set the count in bytes.
DDKSdmaStartChan(m_dmaChanCspiTx);
UINT uiTxStatus = 0;
do
{
DDKSdmaGetBufDescStatus(m_dmaChanCspiTx, 0, &uiTxStatus);
}while (uiTxStatus & DDK_DMA_FLAGS_BUSY);
DEBUGMSG(ZONE_FUNCTION, (TEXT(" uiTxStatus = 0x%X xchTxCnt= 0x%X\r\n"), uiTxStatus, (uiTxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4));
xchTxCnt = (uiTxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4; // division is to get the count in DWORD
}
else
{
// 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
INSREG32(&m_pCSPI->CONREG, CSP_BITFMASK(CSPI_CONREG_XCH),
CSP_BITFVAL(CSPI_CONREG_XCH, CSPI_CONREG_XCH_EN));
// if we completed requested transfers, then we enable
// interrupt for transfer completed (TCEN)
if (xchTxCnt == pXchPkt->xchCnt)
{
if(m_bUsePolling)
{
// wait until transaction is complete
while (!(INREG32(&m_pCSPI->STATREG) & CSP_BITFMASK(CSPI_STATREG_TC)))
;
}
else
{
INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_TCEN),
CSP_BITFVAL(CSPI_INTREG_TCEN, CSPI_INTREG_TCEN_ENABLE));
}
// set flag to indicate requested exchange done
bXchDone = TRUE;
}
// 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
else
{
if(m_bUsePolling)
{
// wait until RH
while (!(INREG32(&m_pCSPI->STATREG) & CSP_BITFMASK(CSPI_STATREG_RH)))
;
}
else
{
if (m_bUseDMA && m_nondmaTransferCount)
{
INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RHEN),
CSP_BITFVAL(CSPI_INTREG_RHEN, CSPI_INTREG_RHEN_ENABLE));
}
else
{
INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RHEN),
CSP_BITFVAL(CSPI_INTREG_RHEN, CSPI_INTREG_RHEN_ENABLE));
}
}
}
while (xchRxCnt < xchTxCnt)
{
// wait for requested transfer interrupt
WaitForSingleObject(m_hIntrEvent, INFINITE);
// disable all interrupts
OUTREG32(&m_pCSPI->INTREG, 0);
// acknowledge transfer complete (w1c)
OUTREG32(&m_pCSPI->STATREG, CSP_BITFMASK(CSPI_STATREG_TC));
// while there is data in Rx FIFO and we have buffer space
while ((INREG32(&m_pCSPI->STATREG) & CSP_BITFMASK(CSPI_STATREG_RR))
&& (xchRxCnt < pXchPkt->xchCnt))
{
if (m_bUseDMA)
{
if (m_dmaTransferCount && !m_isDMADone)
{
DDKSdmaClearBufDescStatus(m_dmaChanCspiRx,0);
DDKSdmaSetBufDesc(m_dmaChanCspiRx, 0,
DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP,
PhysDMABufferAddr.LowPart + CSPI_RECV_OFFSET,
0, DDK_DMA_ACCESS_32BIT, m_dmaTransferCount * 4); //Count should be in Bytes.
DDKSdmaStartChan(m_dmaChanCspiRx);
UINT uiRxStatus = 0;
do
{
DDKSdmaGetBufDescStatus(m_dmaChanCspiRx, 0, &uiRxStatus);
}while (uiRxStatus & DDK_DMA_FLAGS_BUSY);
DEBUGMSG(ZONE_FUNCTION, (TEXT(" uiRxStatus = 0x%X xchRxCnt= 0x%X\r\n"), uiRxStatus, (uiRxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4));
xchRxCnt = (uiRxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4;
MoveDMABuffer(pRxBuf, xchRxCnt * 4,TRUE);
m_isDMADone = TRUE;
// advance the buffer
pRxBuf = (LPVOID) ((UINT) pRxBuf + (xchRxCnt * bufIncr));
}
if (m_nondmaTransferCount)
{
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++;
}
}
else
{
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
OUTREG32(&m_pCSPI->INTREG, 0);
}
else
{
// enable Rx FIFO ready interrupt (RREN)
if (m_bUseDMA && m_nondmaTransferCount)
{
INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RREN),
CSP_BITFVAL(CSPI_INTREG_RREN, CSPI_INTREG_RREN_ENABLE));
}
else
{
INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RREN),
CSP_BITFVAL(CSPI_INTREG_RREN, CSPI_INTREG_RREN_ENABLE));
}
}
}
} // while (xchRxCnt < xchTxCnt)
} // while(!bXchDone)
// Disable the clock gating
BSPCSPIEnableClock(m_Index,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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -