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

📄 cspsocspi.c

📁 WINCE 架构下SPI驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	return bRet;	
}

BOOL   SpiSocClose(PVOID pSpiHandle)
{
	//check 
	//if all devices on bus closed, disable clock
	BOOL bRet = TRUE;
	PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;

	RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocClose Port(%d)\r\n"), pDevHdl->uiHwPort));

	if(!SPI_GRABMUTEX(pDevHdl))
	{
		RETAILMSG (1, (TEXT("+Spi SocClose+ GRABMUTEX failed\r\n") ));
		return FALSE;
	}

	switch (pDevHdl->uiHwPort)
	{
	case SEPARATE_SPI0:	
		if (v_pDriverGlobals->misc.spiDev[0].bSpiOpened)
		{
			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi0, 0);
			v_pDriverGlobals->misc.spiDev[0].bSpiOpened = FALSE;
		}
		break;
	case SEPARATE_SPI1:	
		if (v_pDriverGlobals->misc.spiDev[1].bSpiOpened)
		{
			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi1, 0);
			v_pDriverGlobals->misc.spiDev[1].bSpiOpened = FALSE;
		}
		break;
	default:
		bRet = FALSE;
		RETAILMSG (1, (TEXT("+Spi SocClose+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
	}
       pDevHdl->bSpiOpen = FALSE;
	SPI_RELEASEMUTEX(pDevHdl);
	RETAILMSG (DEBUGPRINT, (TEXT("-Spi SocClose port(%d)\r\n"), pDevHdl->uiHwPort));
	
	return bRet;
}

VOID   SpiSocDeinit(PVOID pSpiHandle)
{
	PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;

	RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocDeinit port(%d)\r\n"),pDevHdl->uiHwPort ));

	if(!SPI_GRABMUTEX(pDevHdl))
	{
		RETAILMSG (1, (TEXT("+Spi SocDeinit+ GRABMUTEX failed\r\n") ));
		return;
	}

	switch (pDevHdl->uiHwPort)
	{
	case SEPARATE_SPI0:	

		if (v_pDriverGlobals->misc.spiDev[0].bSpiInited)
		{
			//RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocDeinit+ tryto StopDispatchThread\r\n") ));
#if SPI_INTR
			if (!StopDispatchThread(pDevHdl))
			{
				RETAILMSG (1, (TEXT("+Spi SocDeinit+ StopDispatchThread failed\r\n")));
				return;
			}

			(HANDLE)v_pDriverGlobals->misc.spiDev[0].hDispatchThread = NULL;
			(HANDLE)v_pDriverGlobals->misc.spiDev[0].hSPIEvent = NULL;
			(HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent = NULL;
#endif	//SPI_INTR
			v_pDriverGlobals->misc.spiDev[0].bSpiInited = FALSE;

			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi0, 0);
			//Free memory
			FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrR));
			(LPVOID)pDevHdl->dwVirtAddrR = NULL;
			FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrW));
			(LPVOID)pDevHdl->dwVirtAddrW = NULL;
		}
		break;
	case SEPARATE_SPI1:	

		if (v_pDriverGlobals->misc.spiDev[1].bSpiInited)
		{
			//RETAILMSG (DEBUGPRINT, (TEXT("+Spi SocDeinit+ tryto StopDispatchThread\r\n") ));
#if SPI_INTR
			if (!StopDispatchThread(pDevHdl))
			{
				RETAILMSG (1, (TEXT("+Spi SocDeinit+ StopDispatchThread failed\r\n")));
				return;
			}

			(HANDLE)v_pDriverGlobals->misc.spiDev[1].hDispatchThread = NULL;
			(HANDLE)v_pDriverGlobals->misc.spiDev[1].hSPIEvent = NULL;
			(HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent = NULL;
#endif	//SPI_INTR
			v_pDriverGlobals->misc.spiDev[1].bSpiInited = FALSE;

			WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), spi1, 0);
			//Free memory
			FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrR));
			(LPVOID)pDevHdl->dwVirtAddrR = NULL;
			FreePhysMem((LPVOID)(pDevHdl->dwVirtAddrW));
			(LPVOID)pDevHdl->dwVirtAddrW = NULL;
		}

		break;
	default:
		RETAILMSG (1, (TEXT("+Spi SocDeinit+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
	}

	SPI_RELEASEMUTEX(pDevHdl);
	
	RETAILMSG (DEBUGPRINT, (TEXT("-Spi SocDeinit port(%d)\r\n"),pDevHdl->uiHwPort));
}

static BOOL SpiWriteCmdOnly(PVOID pSpiHandle, LPVOID pMosiBuf)
{
	PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
	BOOL bRet = TRUE;

	switch (pDevHdl->SpiDevInfo.CmdByteNum)
	{
	case SPI_INFO_CMD_BYTE_NUM_1:	
		WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PBYTE)pMosiBuf);
		break;
	case SPI_INFO_CMD_BYTE_NUM_2:	
		WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PWORD)pMosiBuf);
		break;
	case SPI_INFO_CMD_BYTE_NUM_3:
		WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf & 0xffffff);
		break;
	case SPI_INFO_CMD_BYTE_NUM_4:	
		WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf);
		break;
	default:
		WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf);
		break;
	}

	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxrxen), SPI_CMD_TX_EN);

#if SPI_INTR
	switch (pDevHdl->uiHwPort)
	{
	case SEPARATE_SPI0:	
		WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent, INFINITE);
		break;
	case SEPARATE_SPI1:	
		WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent, INFINITE);
		break;
	default:
		RETAILMSG (1, (TEXT("+Spi + WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
		SPI_RELEASEMUTEX(pDevHdl);
		return FALSE;
	}
#else	//!SPI_INTR
	bRet = SPI_POLLING_FRMEND(pDevHdl);
#endif	//!SPI_INTR

	// Disable the interrupt
	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiinten), 0);
	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxrxen), 0);
	
	SPI_RELEASEMUTEX(pDevHdl);
	return bRet;			
}

BOOL   SpiSocReadData(PVOID pSpiHandle, LPVOID pMosiBuf, DWORD uiMosiBufLen, LPVOID pMisoBuf, DWORD uiMisoBufLen)
{
	//Do in one Func.
	PSPI_DEV_HANDLE pDevHdl = (PSPI_DEV_HANDLE)pSpiHandle;
	BOOL bRet = TRUE;
	int i=0, iDMA_DATA_LEN, iDMA_XLEN;
	DWORD dwReg=0;

	RETAILMSG (DEBUGPRINT,(TEXT("+Spi SocReadData+ entered port(%d)\r\n"),pDevHdl->uiHwPort ));
	 //Parameter validation
	 if((pMosiBuf == NULL && pMisoBuf == NULL) || !pDevHdl->bSpiOpen) 
	 {
		 RETAILMSG (1,(TEXT("+Spi SocReadData+ Parameter Error or Spi not open\r\n") ));
		 return FALSE;
	 }
	 
	 if (SPI_INFO_IO_MODE == pDevHdl->SpiDevInfo.IoMod)
	 {
	        if(!SPI_ParametCheck(pDevHdl,FIFO_LENGTH))
	        {
	        	RETAILMSG (1,(TEXT("+Spi SocReadData+ Parameter Error\r\n") ));
			 return FALSE;
	        }
	 }
	 else
	 {
		 if(!SPI_ParametCheck(pDevHdl,DMA_LENGTH))
		 {
			 RETAILMSG (1,(TEXT("+Spi SocReadData+ Parameter Error\r\n") ));
			  return FALSE;
		 }
	 }
	//Step1: Get Dev Info
	if(!SPI_GRABMUTEX(pDevHdl))
	{
		RETAILMSG (1,(TEXT("+Spi SocReadData+ GRABMUTEX failed\r\n") ));
		return FALSE;
	}
	//Step1 END
	 //Config CmdByteNum,MulDataMod and whether have command bit for this read operation.
	if (SPI_INFO_NO_COMMAND_DATA == pDevHdl->SpiDevInfo.HaveCmdInFrm) 
	{
	     dwReg = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spictrl));
	     dwReg &= ~(0x1 << 17);
	     dwReg = dwReg
			| pDevHdl->SpiDevInfo.CmdByteNum
			| pDevHdl->SpiDevInfo.MulDataMod;
	}
	else
	{
	     dwReg = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spictrl));
	     dwReg |= ((0x1 << 17)
			| pDevHdl->SpiDevInfo.CmdByteNum
			| pDevHdl->SpiDevInfo.MulDataMod);
	}
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spictrl), dwReg);
	//Set transfer length
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxdatalen), pDevHdl->SpiDevInfo.DataLength);

	//Step2: clear and enable interrupts
	//clear interrupts
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiintstatus), SPI_INT_MASK_ALL);
	// Enable the interrupt    
	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spiinten), SPI_INT_FRM_END_MASK);
	//Step2 END

	//Step3: RXFIFO RESET/START
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifoop), SPI_FIFO_RESET);
	WRITE_REGISTER_ULONG (&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifoop), SPI_FIFO_START);
	//Step3 END
        //RETAILMSG (1,(TEXT("+Spi SocR 0x%x\r\n"),(BYTE)READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifodata))));


	//Step4: prepare buffers -- Spicommand, pMisoBuf, txfifodata
	if (SPI_INFO_HAVE_COMMAND_DATA == pDevHdl->SpiDevInfo.HaveCmdInFrm)
	{
		switch (pDevHdl->SpiDevInfo.CmdByteNum)
		{
		case SPI_INFO_CMD_BYTE_NUM_1:	
			WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PBYTE)pMosiBuf);
			break;
		case SPI_INFO_CMD_BYTE_NUM_2:	
			WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PWORD)pMosiBuf);
			break;
		case SPI_INFO_CMD_BYTE_NUM_3:
			WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf & 0xffffff);
			break;
		case SPI_INFO_CMD_BYTE_NUM_4:	
			WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spicommand), *(PDWORD)pMosiBuf);
			break;
		default:
			RETAILMSG (1, (TEXT("+Spi SocReadData+ WRONG command byte number: (%d)\r\n"), pDevHdl->SpiDevInfo.CmdByteNum));
			bRet = FALSE;
			break;
		}
	}
	//Step4 END

	//Step5: DMA
	if (pDevHdl->SpiDevInfo.IoMod != SPI_INFO_IO_MODE)
	{
		//start configure DMA		
		pDevHdl->m_pRawBufR = (BYTE *)(pDevHdl->dwVirtAddrR); //pointer to read memory
	
		if (pDevHdl->m_pRawBufR == NULL)
		{
			RETAILMSG(1, (TEXT("+Spi SocReadData+ m_pRawBufR is NULL.\r\n")));
			SPI_RELEASEMUTEX(pDevHdl);
			return FALSE;
		}

  		switch (pDevHdl->SpiDevInfo.DataFmt)
		{
		case SPI_INFO_TRAN_DATA_FORMAT_8BIT:	
			iDMA_DATA_LEN = pDevHdl->SpiDevInfo.DataLength+1;
			break;
		case SPI_INFO_TRAN_DATA_FORMAT_12BIT:	
		case SPI_INFO_TRAN_DATA_FORMAT_16BIT:	
			iDMA_DATA_LEN = 2*(pDevHdl->SpiDevInfo.DataLength+1);
			break;
		case SPI_INFO_TRAN_DATA_FORMAT_32BIT:	
			iDMA_DATA_LEN = 4*(pDevHdl->SpiDevInfo.DataLength+1);
			break;
		default:
			RETAILMSG (1, (TEXT("+Spi SocReadData+ WRONG data format. (%d)\r\n"), pDevHdl->SpiDevInfo.DataFmt));
			SPI_RELEASEMUTEX(pDevHdl);
			return FALSE;
		} 
		
		iDMA_XLEN = (iDMA_DATA_LEN>>2)+((iDMA_DATA_LEN%4==0)?0:1);

		v_pDMAReg->dmaWidth[USP_REV_DMA_WIDTH_ID] = iDMA_XLEN;	//?

		switch (pDevHdl->uiHwPort)
		{
		case SEPARATE_SPI0:
			WRITE_BITFIELD(struct RSCDmaMuxBits, &((v_pRscRegs)->rscDmaMux), ch12, 1);

			v_pDMAReg->dmaWidth[USP_REV_DMA_WIDTH_ID] = iDMA_XLEN;
			WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[12].xlReg), iDMA_XLEN);
			WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[12].ylReg), 0);	//ylReg = 0, means 1D-DMA

			WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[12].ctrlReg), ws, USP_REV_DMA_WIDTH_ID);
			WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[12].ctrlReg), dir, 0);		//to sdram
			WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[12].ctrlReg), burst, 0);

			//Enable DMA
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn12, 1);
			WRITE_REGISTER_ULONG(&((v_pDMAReg)->dmaChn[12].addrReg), (DWORD)((pDevHdl->dwPhyAddrR)/4));
			break;
		case SEPARATE_SPI1:
			WRITE_BITFIELD(struct RSCDmaMuxBits, &((v_pRscRegs)->rscDmaMux), ch14, 1);
			WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[14].xlReg), iDMA_XLEN);
			WRITE_REGISTER_ULONG(&(v_pDMAReg->dmaChn[14].ylReg), 0);	//ylReg = 0, means 1D-DMA
			WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[14].ctrlReg), ws, USP_REV_DMA_WIDTH_ID);
			WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[14].ctrlReg), dir, 0);
			WRITE_BITFIELD(struct dmaCtrlBits, &((v_pDMAReg)->dmaChn[14].ctrlReg), burst, 0);

			//Enable DMA
			WRITE_BITFIELD(struct dmaIntEnBits, &v_pDMAReg->intEnable, chn14, 1);
			WRITE_REGISTER_ULONG(&((v_pDMAReg)->dmaChn[14].addrReg), (DWORD)((pDevHdl->dwPhyAddrR)/4));
			break;
		default:
			RETAILMSG (1, (TEXT("+Spi SocReadData+ WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
			bRet = FALSE;
			break;
		}
	}
	else
	{
        	// Do nothing
	}
	//Step5 END

	//Step6: RX_EN(TX_EN) -- do early
	WRITE_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spitxrxen), SPI_RX_EN);

	pDevHdl->StatusReg[0] = READ_REGISTER_ULONG(&((((PSPI_SOC_REGS)(pDevHdl->pSpiSocRegs))->v_pSpiSocRegs)->spirxfifostat));
	//Step6 END

#if SPI_INTR
	RETAILMSG (DEBUGPRINT, (TEXT("+Spi READ+ Waiting hFrmendEvent\r\n") ));
	switch (pDevHdl->uiHwPort)
	{
		case SEPARATE_SPI0:	
			WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[0].hFrmendEvent, INFINITE);
			break;
		case SEPARATE_SPI1:	
			WaitForSingleObject((HANDLE)v_pDriverGlobals->misc.spiDev[1].hFrmendEvent, INFINITE);
			break;
		default:
			RETAILMSG (1, (TEXT("+Spi + WRONG spi port num. (%d)\r\n"), pDevHdl->uiHwPort));
			SPI_RELEASEMUTEX(pDevHdl);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -