📄 spi.c
字号:
}
else
{
pSPIregs->CH_CFG = pSpiPrivate->RxSPIregs.CH_CFG;
pSPIregs->CLK_CFG = pSpiPrivate->RxSPIregs.CLK_CFG;
#ifdef POLLING
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(0<<11);
#else
pSPIregs->MODE_CFG = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(RX_TRIG_LEVEL<<11);
#endif
}
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;
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;
}
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")));
}
TotalTimeOut = READ_TIME_OUT_CONSTANT*100*50 + (READ_TIME_OUT_MULTIPLIER)*dwRxCount;
Count = 0;
do
{
while (((pSPIregs ->SPI_STATUS>>13)&0x7f)==FIFO_EMPTY)
{
Count++;
if(TotalTimeOut == Count)
{
// Timeout
RETAILMSG (TRUE, (TEXT("Read timeout!!!\r\n")));
goto LEAVEREAD;
}
}
*(PBYTE)pSpiPrivate->pRxBuffer = pSPIregs->SPI_RX_DATA;
} while(--pSpiPrivate->dwRxCount > 0 && ++(PBYTE)pSpiPrivate->pRxBuffer);
}
LEAVEREAD:
pSpiPrivate->dwRxCount = dwTestCount - pSpiPrivate->dwRxCount;
#ifdef TEST_MODE
do
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] READ BYTE : %02X(dwRxCount %d)\n"), *pTestBuffer, dwTestCount));
} while((--dwTestCount > 0) && ++pTestBuffer);
#endif
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
MASTER_CS_DISABLE;
}
SetEvent(pSpiPublic->hRxDoneEvent);
} while(TRUE);
return 0;
}
DWORD ThreadForSpi(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
volatile S3C6400_SPI_REG *pSPIregs = pSpiPublic->pSPIregs; // for HS-SPI
PSPI_PRIVATE_CONTEXT pSpiPrivate;
DWORD dwRxCount;
DWORD dwTxCount;
RETAILMSG(SPI_MSG,(TEXT("[SPI] ThreadForSpi thread is created \r\n")));
do
{
WaitForSingleObject(pSpiPublic->hSpiEvent, INFINITE);
pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;
if(pSpiPrivate->State == STATE_RXINTR)
{
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
do
{
while (((pSPIregs ->SPI_STATUS>>13)&0x7f)==FIFO_EMPTY);
*(PBYTE)pSpiPrivate->pRxBuffer = pSPIregs->SPI_RX_DATA;
} while(--pSpiPrivate->dwRxCount > 0 && ++(PBYTE)pSpiPrivate->pRxBuffer);
if(pSpiPrivate->dwRxCount ==0)
{
pSPIregs->SPI_INT_EN = 0;
SetEvent(pSpiPublic->hRxIntrDoneEvent);
}
}
else
{
#ifdef POLLING
do
{
while (((pSPIregs ->SPI_STATUS>>13)&0x7f)==FIFO_EMPTY);
*(PBYTE)pSpiPrivate->pRxBuffer = pSPIregs->SPI_RX_DATA;
} while(--pSpiPrivate->dwRxCount > 0 && ++(PBYTE)pSpiPrivate->pRxBuffer);
if(pSpiPrivate->dwRxCount ==0)
{
pSPIregs->SPI_INT_EN = 0;
SetEvent(pSpiPublic->hRxIntrDoneEvent);
}
#else
dwRxCount = ((pSPIregs ->SPI_STATUS>>13) & 0x7f) ;
do
{
*(PBYTE)pSpiPrivate->pRxBuffer = pSPIregs->SPI_RX_DATA;
} while(--pSpiPrivate->dwRxCount > 0 && ++(PBYTE)pSpiPrivate->pRxBuffer && --dwRxCount > 0);
if(pSpiPrivate->dwRxCount ==0)
{
pSPIregs->SPI_INT_EN = 0;
SetEvent(pSpiPublic->hRxIntrDoneEvent);
}
#endif
}
}
else if(pSpiPrivate->State == STATE_TXINTR)
{
if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
{
dwTxCount = FIFO_SIZE -((pSPIregs ->SPI_STATUS>>6) & 0x7f) ;
do
{
pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
} while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer && --dwTxCount > 0);
if(pSpiPrivate->dwTxCount ==0)
{
pSPIregs->SPI_INT_EN = 0;
SetEvent(pSpiPublic->hTxIntrDoneEvent);
}
}
else
{
#ifdef POLLING
do
{
while(((pSPIregs ->SPI_STATUS>>6) & 0x7f)==FIFO_FULL);
pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
} while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer);
if(pSpiPrivate->dwTxCount ==0)
{
pSPIregs->SPI_INT_EN = 0;
SetEvent(pSpiPublic->hTxIntrDoneEvent);
}
#else
dwTxCount = FIFO_SIZE -((pSPIregs ->SPI_STATUS>>6) & 0x7f) ;
do
{
pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
} while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer && --dwTxCount > 0);
if(pSpiPrivate->dwTxCount ==0)
{
pSPIregs->SPI_INT_EN = 0;
SetEvent(pSpiPublic->hTxIntrDoneEvent);
}
#endif
}
}
else
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] UNSOLVED OPERATION\n")));
}
//END_POINT:
InterruptDone(pSpiPublic->dwSpiSysIntr);
} while(TRUE);
return 0;
}
DWORD ThreadForRxDmaDone(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
// volatile S3C6400_SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
// PSPI_PRIVATE_CONTEXT pSpiPrivate;
// DWORD dwOldPerm;
do
{
WaitForSingleObject(pSpiPublic->hRxDmaDoneEvent, INFINITE);
RETAILMSG(SPI_MSG,(TEXT("[SPI] ThreadForRxDmaDone \r\n")));
DMA_set_interrupt_mask(&g_InputDMA);
DMA_clear_interrupt_pending(&g_InputDMA);
SetEvent(pSpiPublic->hRxDmaDoneDoneEvent);
InterruptDone(pSpiPublic->dwRxDmaDoneSysIntr);
DMA_clear_interrupt_mask(&g_InputDMA);
} while(TRUE);
return 0;
}
DWORD ThreadForTxDmaDone(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
// volatile S3C6400_SPI_REG *pSPIregs = pSpiPublic->pSPIregs;
// PSPI_PRIVATE_CONTEXT pSpiPrivate;
// DWORD dwOldPerm;
do
{
WaitForSingleObject(pSpiPublic->hTxDmaDoneEvent, INFINITE);
RETAILMSG(SPI_MSG,(TEXT("[SPI] ThreadForTxDmaDone \r\n")));
DMA_set_interrupt_mask(&g_OutputDMA);
DMA_clear_interrupt_pending(&g_OutputDMA);
SetEvent(pSpiPublic->hTxDmaDoneDoneEvent);
InterruptDone(pSpiPublic->dwTxDmaDoneSysIntr);
DMA_clear_interrupt_mask(&g_OutputDMA);
} while(TRUE);
return 0;
}
void SPI_PowerDown (PSPI_PUBLIC_CONTEXT pPublicSpi)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] ++PowerDown()\n\r")));
//Save SPI Reg
pRestoreSPIregs->CH_CFG = pPublicSpi->pSPIregs->CH_CFG;
pRestoreSPIregs->CLK_CFG = pPublicSpi->pSPIregs->CLK_CFG;
pRestoreSPIregs->MODE_CFG = pPublicSpi->pSPIregs->MODE_CFG;
pRestoreSPIregs->SPI_INT_EN = pPublicSpi->pSPIregs->SPI_INT_EN;
pRestoreSPIregs->SWAP_CFG = pPublicSpi->pSPIregs->SWAP_CFG;
pRestoreSPIregs->FB_CLK_SEL = pPublicSpi->pSPIregs->FB_CLK_SEL;
// Clock Off
pPublicSpi->pSYSCONregs->PCLK_GATE &= ~SPI_POWER_ON;
#if (SPI_CLOCK == EPLL_CLOCK)
pPublicSpi->pSYSCONregs->SCLK_GATE &= ~SPI_SCLK_ON;
#elif (SPI_CLOCK == USB_HOST_CLOCK)
pPublicSpi->pSYSCONregs->SCLK_GATE &= ~SPI_USBHOST_ON;
#endif
RETAILMSG(SPI_MSG,(TEXT("[SPI] --PowerDown()\n\r")));
return;
}
void SPI_Deinit (PSPI_PUBLIC_CONTEXT pPublicSpi)
{
// Delete CS
DeleteCriticalSection(&(pPublicSpi->CsRxAccess));
DeleteCriticalSection(&(pPublicSpi->CsTxAccess));
// Deinitialize Buffer
HalFreeCommonBuffer(0, 0, g_PhysDmaDstBufferAddr, pVirtDmaDstBufferAddr, FALSE);
HalFreeCommonBuffer(0, 0, g_PhysDmaSrcBufferAddr, pVirtDmaSrcBufferAddr, FALSE);
//DMA Channel Stop
DMA_channel_stop(&g_OutputDMA);
DMA_channel_stop(&g_InputDMA);
DMA_release_channel(&g_OutputDMA);
DMA_release_channel(&g_InputDMA);
// Clock Off
pPublicSpi->pSYSCONregs->PCLK_GATE &= ~SPI_POWER_ON;
#if (SPI_CLOCK == EPLL_CLOCK)
pPublicSpi->pSYSCONregs->SCLK_GATE &= ~SPI_SCLK_ON;
#elif (SPI_CLOCK == USB_HOST_CLOCK)
pPublicSpi->pSYSCONregs->SCLK_GATE &= ~SPI_USBHOST_ON;
#endif
//Close Handle
CloseHandle(pPublicSpi->hRxEvent);
CloseHandle(pPublicSpi->hRxDoneEvent);
CloseHandle(pPublicSpi->hRxIntrDoneEvent);
CloseHandle(pPublicSpi->hTxEvent);
CloseHandle(pPublicSpi->hTxDoneEvent);
CloseHandle(pPublicSpi->hTxIntrDoneEvent);
CloseHandle(pPublicSpi->hSpiEvent);
CloseHandle(pPublicSpi->hTxDmaDoneDoneEvent);
CloseHandle(pPublicSpi->hTxDmaDoneEvent);
CloseHandle(pPublicSpi->hRxDmaDoneDoneEvent);
CloseHandle(pPublicSpi->hRxDmaDoneEvent);
CloseHandle(pPublicSpi->hRxThread);
CloseHandle(pPublicSpi->hTxThread);
CloseHandle(pPublicSpi->hSpiThread);
CloseHandle(pPublicSpi->hTxDmaDoneThread);
CloseHandle(pPublicSpi->hRxDmaDoneThread);
//VirtualFree
if (pPublicSpi->pGPIOregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pGPIOregs);
pPublicSpi->pGPIOregs = NULL;
}
if (pPublicSpi->pSPIregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pSPIregs);
pPublicSpi->pSPIregs = NULL;
}
if (pPublicSpi->pDMAC0regs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pDMAC0regs);
pPublicSpi->pDMAC0regs = NULL;
}
if (pPublicSpi->pDMAC1regs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pDMAC1regs);
pPublicSpi->pDMAC1regs = NULL;
}
if (pPublicSpi->pSYSCONregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pSYSCONregs);
pPublicSpi->pSYSCONregs = NULL;
}
//Local Free
LocalFree(pPublicSpi);
return;
}
void SPI_PowerUp (PSPI_PUBLIC_CONTEXT pPublicSpi)
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] ++PowerUp()\n\r")));
// Clock On
pPublicSpi->pSYSCONregs->PCLK_GATE |= SPI_POWER_ON;
#if (SPI_CLOCK == EPLL_CLOCK)
pPublicSpi->pSYSCONregs->SCLK_GATE |= SPI_SCLK_ON;
#elif (SPI_CLOCK == USB_HOST_CLOCK)
pPublicSpi->pSYSCONregs->SCLK_GATE |= SPI_USBHOST_ON;
#endif
//Restore SPI Reg
pPublicSpi->pSPIregs->CH_CFG = pRestoreSPIregs->CH_CFG;
pPublicSpi->pSPIregs->CLK_CFG = pRestoreSPIregs->CLK_CFG;
pPublicSpi->pSPIregs->MODE_CFG = pRestoreSPIregs->MODE_CFG;
pPublicSpi->pSPIregs->SPI_INT_EN = pRestoreSPIregs->SPI_INT_EN;
pPublicSpi->pSPIregs->SWAP_CFG = pRestoreSPIregs->SWAP_CFG;
pPublicSpi->pSPIregs->FB_CLK_SEL = pRestoreSPIregs->FB_CLK_SEL;
RETAILMSG(SPI_MSG,(TEXT("[SPI] --PowerUp()\n\r")));
return;
}
BOOL SPI_Close (DWORD dwOpen)
{
return TRUE;
}
DWORD SPI_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -