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

📄 spi.c

📁 S3C6400的高速SPI源代码.是三星公司新的spi代码架构.很有参考价值.
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -