📄 spi.c
字号:
case SPI_IOCTL_START:
if(pSpiPrivate->State == STATE_ERROR)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] SPI_IOCTL_START ERROR\n")));
bResult = FALSE;
break;
}
pSpiPrivate->State = STATE_IDLE;
RETAILMSG(SPI_MSG,(TEXT("[SPI] SPI STATE : SPI_IOCTL_START\n")));
break;
default:
break;
}
if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, lpInBuf, nInBufSize, ARG_I_PTR)))
{
RETAILMSG(1, (TEXT("SPI_IOControl: CeCloseCallerBuffer failed for input buffer.\r\n")));
return FALSE;
}
CleanUp:
return bResult;
}
DWORD ThreadForTx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile S3C6410_SPI_REG *pSPIregs = NULL;
PSPI_PRIVATE_CONTEXT pSpiPrivate;
DWORD dwTxCount;
PBYTE pTxBuffer;
PBYTE pTestBuffer;
DWORD dwTestCount;
ULONG TimeOut;
ULONG TotalTimeOut;
ULONG WaitReturn;
INT TimeOutCount;
if(pSpiPublic != NULL)
{
pSPIregs = pSpiPublic->pSPIregs;
}
do
{
WaitForSingleObject(pSpiPublic->hTxEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
if(pSpiPrivate->dwTxCount != 0)
{
dwTestCount = dwTxCount = pSpiPrivate->dwTxCount;
}
pTestBuffer = pTxBuffer = pSpiPrivate->pTxBuffer;
RETAILMSG(SPI_MSG,(TEXT("[SPI] pTxBuffer : 0x%X, dwTxCount : %d \r\n"), pTxBuffer, dwTxCount));
//Reset
pSPIregs->CH_CFG |= SW_RST;
while(!(pSPIregs->CH_CFG & SW_RST));
RETAILMSG(SPI_MSG,(TEXT("[SPI] HS SPI reset\n")));
pSPIregs->CH_CFG &= ~SW_RST;
if(pSpiPrivate->bUseTxIntr)
// INT + TX
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : USE INT \r\n")));
pSpiPrivate->State = STATE_TXINTR;
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG|(TX_TRIG_LEVEL<<5);
pSPIregs->SPI_INT_EN = TX_FIFORDY;
pSPIregs->PENDING_CLEAR = TX_UNDERRUN_CLR|TX_OVERRUN_CLR|RX_UNDERRUN_CLR|RX_OVERRUN_CLR|TRAILING_CLR;
pSPIregs->CH_CFG |= TX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
}
//Timeout value setting
TotalTimeOut = WRITE_TIME_OUT_CONSTANT + (WRITE_TIME_OUT_MULTIPLIER/1000)*dwTxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hTxIntrDoneEvent, TimeOut);
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
RETAILMSG (TRUE, (TEXT("Write timeout!!!\r\n")));
goto LEAVEWRITE;
}
TimeOutCount = 1000;
while((((pSPIregs ->SPI_STATUS>>6) & 0x7f) && !(pSPIregs ->SPI_STATUS & TX_DONE))
|| (TimeOutCount>0))
{
TimeOutCount--;
}
}
else if(pSpiPrivate->bUseTxDMA)
// DMA + TX
{
DWORD dwDmaLen = dwTxCount & 0xFFFFF ;
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : USE DMA (TxCount : %d) \r\n"),dwDmaLen));
pSpiPrivate->State = STATE_TXDMA;
//VirtualCopy((PVOID)pSpiPrivate->pTxBuffer, (PVOID)((ULONG) pSpiPrivate->pTxDMABuffer>>8), sizeof(dwTxCount), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG;
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG;
}
if(dwDmaLen > 0)
{
pSPIregs->MODE_CFG |= TX_DMA_ON|DMA_SINGLE;
pSPIregs->CH_CFG |= TX_CH_ON;
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] pSpiPrivate->pTxDMABuffer : 0x%X \r\n"), pSpiPrivate->pTxDMABuffer));
DMA_initialize_channel(&g_OutputDMA, TRUE);
DMA_set_channel_source(&g_OutputDMA, (UINT)pSpiPrivate->pTxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
DMA_set_channel_destination(&g_OutputDMA, (UINT)SPI_TX_DATA_PHY_ADDR, BYTE_UNIT, BURST_1, FIXED);
DMA_set_channel_transfer_size(&g_OutputDMA, dwDmaLen);
DMA_initialize_LLI(&g_OutputDMA, 0);
}
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
}
DMA_channel_start(&g_OutputDMA);
//Timeout value setting
TotalTimeOut = WRITE_TIME_OUT_CONSTANT + (WRITE_TIME_OUT_MULTIPLIER/1000)*dwTxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hTxDmaDoneDoneEvent, TimeOut);
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
RETAILMSG (TRUE, (TEXT("Write timeout!!!\r\n")));
// Stop output DMA
DMA_channel_stop(&g_OutputDMA);
goto LEAVEWRITE;
}
pSpiPrivate->dwTxCount -= dwDmaLen;
pSpiPrivate->pTxBuffer = (((PUINT) pSpiPrivate->pTxBuffer) + dwDmaLen);
}
//VirtualFree((PVOID)pTxBuffer, 0, MEM_RELEASE);
TimeOutCount = 1000;
while((((pSPIregs ->SPI_STATUS>>6) & 0x7f) && !(pSPIregs ->SPI_STATUS & TX_DONE))
|| (TimeOutCount>0))
{
TimeOutCount--;
}
}
else
// POLLING + TX
{
ULONG Count;
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : USE Polling (TxCount : %d) \r\n"), dwTxCount));
pSPIregs->CH_CFG = pSpiPrivate->TxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->TxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->TxSPIregs.MODE_CFG;
pSPIregs->CH_CFG |= TX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
}
TotalTimeOut = WRITE_TIME_OUT_CONSTANT*100*50 + (WRITE_TIME_OUT_MULTIPLIER)*dwTxCount;
Count = 0;
do
{
while(((pSPIregs ->SPI_STATUS>>6) & 0x7f)==FIFO_FULL)
{
Count++;
if(TotalTimeOut == Count)
{
// Timeout
RETAILMSG (TRUE, (TEXT("Write timeout!!!\r\n")));
goto LEAVEWRITE;
}
}
pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
} while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer);
TimeOutCount = 1000;
while((((pSPIregs ->SPI_STATUS>>6) & 0x7f) && !(pSPIregs ->SPI_STATUS & TX_DONE))
|| (TimeOutCount>0))
{
TimeOutCount--;
}
}
LEAVEWRITE:
#ifdef TEST_MODE
do
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] WRITE BYTE : %02X(dwTxCount : %d)\n"), *pTestBuffer, dwTestCount));
} while( (--dwTestCount > 0) && ++pTestBuffer);
#endif
RETAILMSG(FALSE,(TEXT("[SPI] TX_CH_OFF \n")));
pSPIregs->CH_CFG &= ~TX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
MASTER_CS_DISABLE;
}
SetEvent(pSpiPublic->hTxDoneEvent);
} while(TRUE);
return 0;
}
DWORD ThreadForRx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile S3C6410_SPI_REG *pSPIregs = NULL;
PSPI_PRIVATE_CONTEXT pSpiPrivate;
DWORD dwRxCount;
PBYTE pRxBuffer;
PBYTE pTestBuffer;
DWORD dwTestCount;
ULONG TimeOut;
ULONG TotalTimeOut;
ULONG WaitReturn;
if(pSpiPublic != NULL)
{
pSPIregs = pSpiPublic->pSPIregs;
}
do
{
WaitForSingleObject(pSpiPublic->hRxEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
if(pSpiPrivate->dwRxCount != 0)
{
dwTestCount = dwRxCount = pSpiPrivate->dwRxCount;
}
pTestBuffer = pRxBuffer = pSpiPrivate->pRxBuffer;
RETAILMSG(SPI_MSG,(TEXT("[SPI] pRxBuffer : 0x%X, dwRxCount : %d \r\n"), pRxBuffer, dwRxCount));
//Reset
pSPIregs->CH_CFG |= SW_RST;
while(!(pSPIregs->CH_CFG & SW_RST));
RETAILMSG(SPI_MSG,(TEXT("[SPI] HS SPI reset\n")));
pSPIregs->CH_CFG &= ~SW_RST;
if(pSpiPrivate->bUseRxIntr)
//INT Mode + RX
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : USE INT \r\n")));
pSpiPrivate->State = STATE_RXINTR;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(RX_TRIG_LEVEL<<11);
pSPIregs->PACKET_COUNT = PACKET_CNT_EN | (pSpiPrivate->dwRxCount) ;
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(RX_TRIG_LEVEL<<11);
}
pSPIregs->SPI_INT_EN = RX_FIFORDY;
pSPIregs->PENDING_CLEAR = TX_UNDERRUN_CLR|TX_OVERRUN_CLR|RX_UNDERRUN_CLR|RX_OVERRUN_CLR|TRAILING_CLR;
pSPIregs->CH_CFG |= RX_CH_ON;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : SLAVE MODE \r\n")));
}
//Timeout value setting
TotalTimeOut = READ_TIME_OUT_CONSTANT + (READ_TIME_OUT_MULTIPLIER/1000)*dwRxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hRxIntrDoneEvent, TimeOut);
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
RETAILMSG (TRUE, (TEXT("Read timeout!!!\r\n")));
goto LEAVEREAD;
}
}
else if(pSpiPrivate->bUseRxDMA)
//DMA Mode + Rx
{
DWORD dwDmaLen = (pSpiPrivate->dwRxCount & 0xFFFFF);
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : USE DMA \r\n")));
pSpiPrivate->State = STATE_RXDMA;
//VirtualCopy((PVOID)pSpiPrivate->pRxBuffer, (PVOID)((ULONG) pSpiPrivate->pRxDMABuffer>>8), sizeof(dwRxCount), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);
//Reset
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG;
pSPIregs->PACKET_COUNT = PACKET_CNT_EN | (pSpiPrivate->dwRxCount) ;
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG;
}
if(dwDmaLen > 0)
{
pSPIregs->MODE_CFG |= RX_DMA_ON|DMA_SINGLE;
pSPIregs->CH_CFG |= RX_CH_ON;
{
DMA_initialize_channel(&g_InputDMA, TRUE);
DMA_set_channel_source(&g_InputDMA, (UINT)SPI_RX_DATA_PHY_ADDR, BYTE_UNIT, BURST_1, FIXED);
DMA_set_channel_destination(&g_InputDMA, (UINT)pSpiPrivate->pRxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
DMA_set_channel_transfer_size(&g_InputDMA, dwDmaLen);
DMA_initialize_LLI(&g_InputDMA, 0);
}
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : MASTER MODE \r\n")));
MASTER_CS_ENABLE;
}
else
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : SLAVE MODE \r\n")));
}
DMA_channel_start(&g_InputDMA);
//Timeout value setting
TotalTimeOut = READ_TIME_OUT_CONSTANT + (READ_TIME_OUT_MULTIPLIER/1000)*dwRxCount;
TimeOut = TotalTimeOut;
WaitReturn = WaitForSingleObject(pSpiPublic->hRxDmaDoneDoneEvent, TimeOut);
if ( WAIT_TIMEOUT == WaitReturn )
{
// Timeout
RETAILMSG (TRUE, (TEXT("Read timeout!!!\r\n")));
// Stop input DMA
DMA_channel_stop(&g_InputDMA);
goto LEAVEREAD;
}
pSpiPrivate->dwRxCount -= dwDmaLen;
pSpiPrivate->pRxBuffer = (PBYTE) (((PUINT) pSpiPrivate->pRxBuffer) + dwDmaLen);
}
//VirtualFree((PVOID)pRxBuffer, 0, MEM_RELEASE);
}
else
{
//POLLING Mode + RX
ULONG Count;
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : USE Polling (RxCount : %d) \r\n"), dwRxCount));
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -