📄 cspsocspi.c
字号:
/*
* Copyright (c) 2002-2003 Centrality Comunications Inc.
* All Rights Reserved.
*
* Confidential and Proprietary to Centrality Communications Inc.
*
* Module Name:
* CspSocSpi.c
* Abstract:
*
*
* Author: LiJiang
* Functions:
*
*/
#include <drvlib.h>
#include <Spi.h>
#include <SocSpi.h>
#define DEBUGPRINT 0
#define SPI_INTR 1
SPI_SOC_REGS g_spi0_soc_regs;
SPI_SOC_REGS g_spi1_soc_regs;
static const UINT msWaitLimit = 200;
OALSYSINFO g_oalSysInfo;
static void DumpSPIDevInfo(PVOID pSpiHandle);
static BOOL SPI_POLLING_FRMEND(PVOID pSpiHandle);
#define SPI_SEM_TIMEOUT 10
#define FIFO_LENGTH 32 //bytes
#define DMA_LENGTH 16*1024 //bytes
#define SPI0_MUTEX_NAME TEXT("SPI0")
#define SPI1_MUTEX_NAME TEXT("SPI1")
__inline VOID SPI_RELEASEMUTEX(PSPI_DEV_HANDLE pSpiHandle)
{
ReleaseMutex(pSpiHandle->v_hSpiMutex);
}
__inline BOOL SPI_GRABMUTEX(PSPI_DEV_HANDLE pSpiHandle)
{
if(WaitForSingleObject(pSpiHandle->v_hSpiMutex, SPI_SEM_TIMEOUT)==WAIT_OBJECT_0)
{
return TRUE;
}
RETAILMSG(1,(TEXT("Grab mutex fail\r\n")));
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
static BOOL SPI_POLLING_FRMEND(PVOID pSpiHandle)
{
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
UINT iTick = 0;
BOOL bRet = TRUE;
Sleep(0);
//polling
iTick = GetTickCount();
while (0 == ((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus & SPI_INT_FRM_END_MASK))
{
Sleep(0);
if (GetTickCount() - iTick > msWaitLimit)
{
RETAILMSG(1, (L"+SPI_POLLING_FRMEND+ failed\r\n"));
bRet = FALSE;
break;
}
}
//clean all interrupt
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus), SPI_INT_MASK_ALL);//xh add
return bRet;
}
static BOOL SPI_ParametCheck(PVOID pHandle, DWORD dwLen)
{
BOOL bFlag = TRUE;
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pHandle;
switch (pDevHdl->SpiDevInfo.DataFmt)
{
case SPI_INFO_TRAN_DATA_FORMAT_8BIT:
if(pDevHdl->SpiDevInfo.DataLength > (dwLen-1))
{
bFlag = FALSE;
}
break;
case SPI_INFO_TRAN_DATA_FORMAT_12BIT:
case SPI_INFO_TRAN_DATA_FORMAT_16BIT:
if(pDevHdl->SpiDevInfo.DataLength > (dwLen/2-1))
{
bFlag = FALSE;
}
break;
case SPI_INFO_TRAN_DATA_FORMAT_32BIT:
if(pDevHdl->SpiDevInfo.DataLength > (dwLen/4-1))
{
bFlag = FALSE;
}
break;
default:
RETAILMSG(1, (TEXT("+Spi SocWriteData+ WRONG data format: (%d)\r\n"), pDevHdl->SpiDevInfo.DataFmt));
bFlag = FALSE;
break;
}
return bFlag;
}
#if SPI_INTR
BOOL SPIEventHandler(PVOID pSpiHandle) //process int
{
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
DWORD dwSpiIntStatus;
DWORD dwSpiIntEnable;
if (pDevHdl->bKillThread)
{
return FALSE;
}
dwSpiIntEnable = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiinten));
dwSpiIntStatus = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus));
// The interrupt value is valid
dwSpiIntStatus &= SPI_INT_MASK_ALL;
//RETAILMSG (DEBUGPRINT, (TEXT("+Spi + dwSpiIntStatus. (0x%x)\r\n"), dwSpiIntStatus));
if(dwSpiIntStatus & SPI_INT_FRM_END_MASK)
{
//set event
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
SetEvent((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent);
break;
case SEPARATE_SPI1:
SetEvent((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent);
break;
default:
RETAILMSG (1, (TEXT("+Spi + WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
return FALSE;
}
//clean interrupt
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus), SPI_INT_FRM_END_MASK);
}
else
{
RETAILMSG(DEBUGPRINT, (TEXT("+SPI EventHandler+ dwSpiIntStatus: 0x%x\r\n"), dwSpiIntStatus));
//TODO: check which interrupt happened
}
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus), SPI_INT_MASK_ALL);
//write back the IntEnable
WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiinten), dwSpiIntEnable);
return TRUE;
}
//a thread that detect hw interrupt and send to process after open
static DWORD WINAPI SPIDispatchThread(LPVOID pContext)
{
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pContext;
// Wait for the event that any serial port action creates.
while(!pDevHdl->bKillThread)
{
//WaitForSingleObject(pDevHdl->hSPIEvent, INFINITE);
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent, INFINITE);
break;
case SEPARATE_SPI1:
WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent, INFINITE);
break;
default:
RETAILMSG (1, (TEXT("+Spi + WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
return FALSE;
}
if (!SPIEventHandler(pDevHdl))
{
break;
}
//ResetEvent(pDevHdl->hSPIEvent);
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
ResetEvent((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent);
InterruptDone(g_oalSysInfo.spiInfo[0].dwSysIntr);
break;
case SEPARATE_SPI1:
ResetEvent((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent);
InterruptDone(g_oalSysInfo.spiInfo[1].dwSysIntr);
break;
default:
RETAILMSG (1, (TEXT("+Spi SPIDispatchThread+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
return FALSE;
break;
}
}
return TRUE;
}
static BOOL StartDispatchThread(PVOID pSpiHandle) //start the int detect thread in open
{
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
ULONG priority256;
DWORD dHwIntr=0;
// Set up the dispatch thread and it's kill flag.
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
//hFrmendEvent
(HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent = CreateEvent(0,FALSE,FALSE,NULL);
//hSPIEvent
(HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent = CreateEvent(0,FALSE,FALSE,NULL);
// Initialize SPI0 interrupt
dHwIntr = g_oalSysInfo.spiInfo[0].dwSysIntr;
if (!InterruptInitialize(dHwIntr, (HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent, NULL, 0))
{
RETAILMSG(1, (TEXT("+Start DispatchThread+ InterruptInitialize spiInfo[0] failed %d\r\n"), GetLastError()));
if((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent);
if((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent);
return FALSE;
}
InterruptDone(g_oalSysInfo.spiInfo[0].dwSysIntr);
pDevHdl->bKillThread = FALSE;
//SPIDispatchThread
(HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread = CreateThread(NULL,0, SPIDispatchThread, (LPVOID)pDevHdl, 0,NULL);
priority256 = CeGetThreadPriority((HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread);
RETAILMSG(1, (TEXT("priority256=%d\r\n"),priority256));
CeSetThreadPriority((HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread, 60);
if ((HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread == NULL)
{
RETAILMSG(1, (TEXT("+Start DispatchThread+ hDispatchThread is NULL\r\n")));
if((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent);
if((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent);
return FALSE;
}
break;
case SEPARATE_SPI1:
//hFrmendEvent
(HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent = CreateEvent(0,FALSE,FALSE,NULL);
//hSPIEvent
(HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent = CreateEvent(0,FALSE,FALSE,NULL);
// Initialize SPI1 interrupt
dHwIntr = g_oalSysInfo.spiInfo[1].dwSysIntr;
if (!InterruptInitialize(dHwIntr, (HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent, NULL, 0))
{
RETAILMSG(1, (TEXT("+Start DispatchThread+ InterruptInitialize spiInfo[1] failed %d\r\n"), GetLastError()));
if((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent);
if((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent);
return FALSE;
}
InterruptDone(g_oalSysInfo.spiInfo[1].dwSysIntr);
pDevHdl->bKillThread = FALSE;
//hDispatchThread
(HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread = CreateThread(NULL,0, SPIDispatchThread, (LPVOID)pDevHdl, 0,NULL);
priority256 = CeGetThreadPriority((HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread);
RETAILMSG(1, (TEXT("priority256=%d\r\n"),priority256));
CeSetThreadPriority((HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread, 60);
if ((HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread == NULL)
{
RETAILMSG(1, (TEXT("+Start DispatchThread+ hDispatchThread is NULL\r\n")));
if((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent);
if((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent);
return FALSE;
}
break;
default:
RETAILMSG (1, (TEXT("+Spi + WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
return FALSE;
}
return TRUE;
}
static BOOL StopDispatchThread(PVOID pSpiHandle) //stop the int detect thread in open
{
PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
HANDLE pThisThread = GetCurrentThread();
DWORD dwDispatchRet = 0;
RETAILMSG (DEBUGPRINT, (TEXT("+SPI StopDispatchThread+ entered\r\n") ));
switch (pDevHdl->uiHwPort)
{
case SEPARATE_SPI0:
/* If we have an interrupt handler thread, kill it */
if ((HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread != NULL)
{
pDevHdl->bKillThread = TRUE;
SetEvent((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent);
if (WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread, 1000) == WAIT_TIMEOUT)
{
RETAILMSG(1, (TEXT("SPI0 StopDispatchThread timeout 1000ms\r\n")));
}
else
{
RETAILMSG(1, (TEXT("SPI0 StopDispatchThread success\r\n")));
}
CloseHandle ((HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread);
}
if((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent);
if((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent)
CloseHandle((HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent);
InterruptDisable(g_oalSysInfo.spiInfo[0].dwSysIntr);
break;
case SEPARATE_SPI1:
/* If we have an interrupt handler thread, kill it */
if ((HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread != NULL)
{
pDevHdl->bKillThread = TRUE;
SetEvent((HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent);
if (WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread, 1000) == WAIT_TIMEOUT)
{
RETAILMSG(1, (TEXT("SPI1 StopDispatchThread timeout 1000ms\r\n")));
}
else
{
RETAILMSG(1, (TEXT("SPI1 StopDispatchThread success\r\n")));
}
CloseHandle ((HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -