⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cspsocspi.c

📁 WINCE 架构下SPI驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 
* 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 + -