📄 spi.c
字号:
return (DWORD) NULL;
}
}
DWORD
SPI_Read(
DWORD hOpenContext,
LPVOID pBuffer,
DWORD Count)
{
PSPI_PRIVATE_CONTEXT pSpiPrivate = (PSPI_PRIVATE_CONTEXT)hOpenContext;
PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
// DWORD dwReadSize;
HRESULT hr;
PBYTE g_pMappedEmbedded;
PBYTE g_pMarshalled;
//param check
if(pSpiPrivate->State != STATE_IDLE)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] READ ERROR : STATE IS NOT IDLE\n")));
return 0;
}
RETAILMSG(SPI_MSG,(TEXT("[SPI] pBuffer : 0x%X, Count : %d\n"), pBuffer, Count));
hr = CeOpenCallerBuffer((PVOID*) &g_pMappedEmbedded, pBuffer, Count, ARG_IO_PTR, FALSE);
hr = CeAllocAsynchronousBuffer((PVOID*) &g_pMarshalled, g_pMappedEmbedded, Count, ARG_IO_PTR);
if(pSpiPrivate->bUseRxDMA)
{
pSpiPrivate->pRxBuffer = pVirtDmaDstBufferAddr;
pSpiPrivate->pRxDMABuffer = (LPVOID)DmaDstAddress;
}
else
{
pSpiPrivate->pRxBuffer = g_pMarshalled;
}
RETAILMSG(SPI_MSG,(TEXT("[SPI] g_pMappedEmbedded 0x%x\n"),g_pMappedEmbedded));
RETAILMSG(SPI_MSG,(TEXT("[SPI] g_pMarshalled 0x%x\n"),g_pMarshalled));
pSpiPrivate->dwRxCount = Count;
pSpiPublic->pSpiPrivate = pSpiPrivate;
SetEvent(pSpiPublic->hRxEvent);
//Thread call
WaitForSingleObject(pSpiPublic->hRxDoneEvent, INFINITE);
pSpiPrivate->State = STATE_IDLE;
if(pSpiPrivate->bUseRxDMA)
{
memcpy(g_pMarshalled, pVirtDmaDstBufferAddr,Count);
}
hr = CeFreeAsynchronousBuffer((PVOID)g_pMarshalled, g_pMappedEmbedded, Count, ARG_IO_PTR);
hr = CeCloseCallerBuffer((PVOID) g_pMappedEmbedded, pBuffer, Count, ARG_IO_PTR);
RETAILMSG(SPI_MSG,(TEXT("[SPI] SPI_Read : Return Value : %d\n\n"),pSpiPrivate->dwRxCount));
return pSpiPrivate->dwRxCount ;
}
DWORD
SPI_Write(
DWORD hOpenContext,
LPVOID pBuffer,
DWORD Count)
{
PSPI_PRIVATE_CONTEXT pSpiPrivate = (PSPI_PRIVATE_CONTEXT)hOpenContext;
PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
HRESULT hr;
PBYTE g_pMappedEmbedded;
PBYTE g_pMarshalled;
//param check
if(pSpiPrivate->State != STATE_IDLE) {
RETAILMSG(SPI_MSG,(TEXT("[SPI] WRITE ERROR : STATE IS NOT IDLE\n")));
return 0;
}
RETAILMSG(SPI_MSG,(TEXT("[SPI] pBuffer : 0x%X, Count : %d\n"), pBuffer, Count));
hr = CeOpenCallerBuffer((PVOID*) &g_pMappedEmbedded, pBuffer, Count, ARG_IO_PTR, FALSE);
hr = CeAllocAsynchronousBuffer((PVOID*) &g_pMarshalled, g_pMappedEmbedded, Count, ARG_IO_PTR);
if(pSpiPrivate->bUseTxDMA)
{
memcpy(pVirtDmaSrcBufferAddr,g_pMarshalled, Count);
pSpiPrivate->pTxBuffer = pVirtDmaSrcBufferAddr;
pSpiPrivate->pTxDMABuffer = (LPVOID)DmaSrcAddress;
}
else
{
pSpiPrivate->pTxBuffer = (LPVOID)g_pMarshalled;
}
RETAILMSG(SPI_MSG,(TEXT("[SPI] g_pMappedEmbedded 0x%x\n"),g_pMappedEmbedded));
RETAILMSG(SPI_MSG,(TEXT("[SPI] g_pMarshalled 0x%x\n"),g_pMarshalled));
pSpiPrivate->dwTxCount = Count;
pSpiPublic->pSpiPrivate = pSpiPrivate;
SetEvent(pSpiPublic->hTxEvent);
//Thread call
WaitForSingleObject(pSpiPublic->hTxDoneEvent, INFINITE);
pSpiPrivate->State = STATE_IDLE;
hr = CeFreeAsynchronousBuffer((PVOID)g_pMarshalled, g_pMappedEmbedded, Count, ARG_IO_PTR);
hr = CeCloseCallerBuffer((PVOID) g_pMappedEmbedded, pBuffer, Count, ARG_IO_PTR);
RETAILMSG(SPI_MSG,(TEXT("[SPI] SPI_Write : Return Value : %d\n"),pSpiPrivate->dwTxCount));
return pSpiPrivate->dwTxCount;
}
BOOL
SPI_IOControl(
DWORD dwInst,
DWORD dwIoControlCode,
PBYTE lpInBuf,
DWORD nInBufSize,
PBYTE lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesRetruned)
{
PSPI_PRIVATE_CONTEXT pSpiPrivate = (PSPI_PRIVATE_CONTEXT)dwInst;
PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
volatile S3C6400_SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
volatile S3C6400_SPI_REG *pRxSPIregs = &pSpiPrivate->RxSPIregs;
volatile S3C6400_SPI_REG *pTxSPIregs = &pSpiPrivate->TxSPIregs;
PSET_CONFIG pSetConfig;
BOOL bResult = TRUE;
switch(dwIoControlCode)
{
case SPI_IOCTL_SET_CONFIG:
if( nInBufSize != sizeof(SET_CONFIG) )
{
bResult = FALSE;
break;
}
pSetConfig = (PSET_CONFIG) lpInBuf;
//===========================================COMMON PART===========================================
pSpiPrivate->dwTimeOutVal = pSetConfig->dwTimeOutVal;
pSpiPrivate->dwMode = pSetConfig->dwMode;
pSpiPrivate->dwPrescaler = pSetConfig->dwPrescaler;
pSpiPrivate->bUseRxDMA = pSetConfig->bUseRxDMA;
pSpiPrivate->bUseRxIntr = pSetConfig->bUseRxIntr;
pSpiPrivate->bUseTxDMA = pSetConfig->bUseTxDMA;
pSpiPrivate->bUseTxIntr = pSetConfig->bUseTxIntr;
pRxSPIregs->CH_CFG = CPOL_RISING|CPHA_FORMAT_A;
#if (SPI_CLOCK == EPLL_CLOCK)
pRxSPIregs->CLK_CFG = CLKSEL_EPLL|(pSpiPrivate->dwPrescaler);
#elif (SPI_CLOCK == USB_HOST_CLOCK)
pRxSPIregs->CLK_CFG = CLKSEL_USBCLK|(pSpiPrivate->dwPrescaler);
#elif (SPI_CLOCK == PCLOCK)
pRxSPIregs->CLK_CFG = CLKSEL_PCLK|(pSpiPrivate->dwPrescaler);
#endif
//pRxSPIregs->MODE_CFG = TRAIL_CNT(0x3FF);
pRxSPIregs->MODE_CFG = MODE_DEFAULT;
pTxSPIregs->CH_CFG = pRxSPIregs->CH_CFG;
pTxSPIregs->CLK_CFG = pRxSPIregs->CLK_CFG;
pTxSPIregs->MODE_CFG = pRxSPIregs->MODE_CFG;
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
pRxSPIregs->CH_CFG |= SPI_MASTER;
pRxSPIregs->CLK_CFG |= ENCLK_ENABLE;
pTxSPIregs->CH_CFG |= SPI_MASTER;
pTxSPIregs->CLK_CFG |= ENCLK_ENABLE;
}
else if(pSpiPrivate->dwMode == SPI_SLAVE_MODE)
{
pRxSPIregs->CH_CFG |= SPI_SLAVE;
pRxSPIregs->CLK_CFG |= ENCLK_DISABLE;
pTxSPIregs->CH_CFG |= SPI_SLAVE;
pTxSPIregs->CLK_CFG |= ENCLK_DISABLE;
}
else
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] It's not supported MODE\n")));
pSpiPrivate->State = STATE_ERROR;
break;
}
break;
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;
}
return bResult;
}
DWORD ThreadForTx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile S3C6400_SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
PSPI_PRIVATE_CONTEXT pSpiPrivate;
DWORD dwTxCount;
PBYTE pTxBuffer;
PBYTE pTestBuffer;
DWORD dwTestCount;
ULONG TimeOut;
ULONG TotalTimeOut;
ULONG WaitReturn;
do
{
WaitForSingleObject(pSpiPublic->hTxEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
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;
Sleep(5);
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;
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|(TX_TRIG_LEVEL<<5);
}
else
{
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;
}
while(((pSPIregs ->SPI_STATUS>>6) & 0x7f));
while(!(pSPIregs ->SPI_STATUS & TX_DONE));
}
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);
while(((pSPIregs ->SPI_STATUS>>6) & 0x7f));
while(!(pSPIregs ->SPI_STATUS & TX_DONE));
}
else
// POLLING + TX
{
ULONG Count;
RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : USE Polling (TxCount : %d) \r\n"), dwTxCount));
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;
}
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);
while(((pSPIregs ->SPI_STATUS>>6) & 0x7f));
while(!(pSPIregs ->SPI_STATUS & TX_DONE));
}
LEAVEWRITE:
pSpiPrivate->dwTxCount = dwTestCount - pSpiPrivate->dwTxCount;
#ifdef TEST_MODE
do
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] WRITE BYTE : %02X(dwTxCount : %d)\n"), *pTestBuffer, dwTestCount));
} while( (--dwTestCount > 0) && ++pTestBuffer);
#endif
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
MASTER_CS_DISABLE;
}
SetEvent(pSpiPublic->hTxDoneEvent);
} while(TRUE);
return 0;
}
DWORD ThreadForRx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile S3C6400_SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
PSPI_PRIVATE_CONTEXT pSpiPrivate;
DWORD dwRxCount;
PBYTE pRxBuffer;
PBYTE pTestBuffer;
DWORD dwTestCount;
ULONG TimeOut;
ULONG TotalTimeOut;
ULONG WaitReturn;
do
{
WaitForSingleObject(pSpiPublic->hRxEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
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;
Sleep(5);
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) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -