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

📄 spi.c

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