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

📄 ssp_driver.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//*********************************************************************
//* Software that is described herein is for illustrative purposes only  
//* which provides customers with programming information regarding the  
//* products. This software is supplied "AS IS" without any warranties.  
//* NXP Semiconductors assumes no responsibility or liability for the 
//* use of the software, conveys no license or title under any patent, 
//* copyright, or mask work right to the product. NXP Semiconductors 
//* reserves the right to make changes in the software without 
//* notification. NXP Semiconductors also make no representation or 
//* warranty that such application will be suitable for the specified 
//* use without further testing or modification. 
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// ssp_driver.h
//
// SSP driver
//

#include <windows.h>
#include <nkintr.h>
#include <CEDDK.h>
#include "bsp.h"
#include "bsp_ssp.h"
#include "drv_ioctl_funcs.h"
#include "lpc32xx_ssp.h"
#include "lpc32xx_clkpwr.h"
#include "lpc32xx_gpio.h"

// Device context instance
typedef struct
{
	SSP_REGS_T *pSSPRegs;
	CLKPWR_REGS_T *pClkPwrRegs; // Pointer to CLKPWR regs
	GPIO_REGS_T *pGPIORegs;     // Pointer to GPIO regs
	DWORD SSPsysIntr;           // SysIntr value for device
	HANDLE sspEvent;            // Interrupt event handler
	HANDLE sspLock;             // Mutex for SSP access lock
	int    sspNum;              // 0 for SSP0, 1 for SSP1
	class bspssp *pSSPClass;    // Allocated SSP control class
} SSP_DRVCTL_T;
static SSP_DRVCTL_T sspDrv[2] = {
	{NULL, NULL, NULL, SYSINTR_UNDEFINED, NULL, NULL, 0, NULL},
	{NULL, NULL, NULL, SYSINTR_UNDEFINED, NULL, NULL, 1, NULL}};

// Number of open instances
static int sspInstances[2] = {0, 0};

//------------------------------------------------------------------------------
//
// dump_regs
//
// Dump current SSP registers, debug function
//
void dump_regs(SSP_REGS_T *pRegs)
{
	UINT32 *p32 = (UINT32 *) pRegs;

	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;
	RETAILMSG(1, (_T("SSP Reg 0x%x = 0x%08x!\r\n"), p32, *p32));
	p32++;

}

//------------------------------------------------------------------------------
//
// SSP_Lock
//
// Lock access to SSP registers
//
static void SSP_Lock(HANDLE lckHndl) {
	WaitForSingleObject(lckHndl, 150);
}

//------------------------------------------------------------------------------
//
// SSP_Unlock
//
// Unlock access to SSP registers
//
static void SSP_Unlock(HANDLE lckHndl) {
	ReleaseMutex(lckHndl);
}

//------------------------------------------------------------------------------
//
// SSPPeriphDown
//
// Disables clocking and power state
//
static void SSPPeriphDown(DWORD hDeviceContext)
{
	SSP_DRVCTL_T *pDev = (SSP_DRVCTL_T *) hDeviceContext;

	// Disable clock for this device
	if (pDev->sspNum == 0)
	{
		pDev->pClkPwrRegs->clkpwr_ssp_blk_ctrl &= ~CLKPWR_SSPCTRL_SSPCLK0_EN;
	}
	else
	{
		pDev->pClkPwrRegs->clkpwr_ssp_blk_ctrl &= ~CLKPWR_SSPCTRL_SSPCLK1_EN;
	}
}

//------------------------------------------------------------------------------
//
// SSPPeriphUp
//
// Enables peripheral clocking and power state
//
extern "C" void SSPPeriphUp(DWORD hDeviceContext)
{
	SSP_DRVCTL_T *pDev = (SSP_DRVCTL_T *) hDeviceContext;

	// Enable clock for this device
	if (pDev->sspNum == 0)
	{
		pDev->pClkPwrRegs->clkpwr_ssp_blk_ctrl |= CLKPWR_SSPCTRL_SSPCLK0_EN;
	}
	else
	{
		pDev->pClkPwrRegs->clkpwr_ssp_blk_ctrl |= CLKPWR_SSPCTRL_SSPCLK1_EN;
	}
}

//------------------------------------------------------------------------------
//
// SSP_CS_Setup
//
// Sets the control function for the SSP chip select
//
void SSP_CS_Setup(SSP_DRVCTL_T *pDev,
				  BOOL lockedCS)
{
	if (pDev->sspNum == 0)
	{
		if (lockedCS == TRUE)
		{
			// GPIO controls SSP0 CS
			pDev->pGPIORegs->pio_mux_clr = PIO1_GPIO05_SSEL0;
			pDev->pGPIORegs->pio_dir_set = OUTP_STATE_GPIO(5);
		}
		else
		{
			// SSP0 controls SSP0 CS
			pDev->pGPIORegs->pio_mux_set = PIO1_GPIO05_SSEL0;
			pDev->pGPIORegs->pio_dir_clr = OUTP_STATE_GPIO(5);
		}
	}
	else
	{
		// Not supported on Phytec board
		// TBD Customer will need to implement for their own board
	}
}

//------------------------------------------------------------------------------
//
// SSP_Transfer
//
// SSP transaction handler, handles both RX and TX for a specific channel
//
static BOOL SSP_Transfer(SSP_DRVCTL_T *pDev,
						 SSP_SEND_XFER_T *sspout,
						 SSP_RECV_XFER_T *sspin)
{
	SSP_XFER_T sspxfer;
	BOOL waitLoop;
	DWORD rsts;
	DWORD inBuff, outBuff;
	int toRecv, toSend;

	// Drive the chip select low (if GPIO is used for CS)
	if (pDev->sspNum == 0)
	{
		pDev->pGPIORegs->pio_outp_clr = OUTP_STATE_GPIO(5);
	}
	else
	{
		// Not supported on Phytec board
		// TBD Customer will need to implement for their own board
	}

	// Save buffer pointers and transfer sizes
	inBuff = (DWORD) sspin->recvBuff;
	outBuff = (DWORD) sspout->sendBuff;
	toRecv = sspin->recvBuffSize;
	toSend = sspout->sendBuffBytes;

	// Wait for an interrupt until all data has been transferred
	waitLoop = TRUE;
	while (waitLoop == TRUE)
	{
		// Setup the transfer
		sspxfer.recvBuff = (void *) inBuff;
		sspxfer.recvBuffSize = toRecv;
		sspxfer.sendBuff = (void *) outBuff;
		sspxfer.sendBuffBytes = toSend;

		// Start the transfer
		pDev->pSSPClass->bspsspInt(&sspxfer);

		// Update counts from actual values
		inBuff += (DWORD) sspxfer.recvBuffBytesFilled;
		toRecv -= sspxfer.recvBuffBytesFilled;
		outBuff += (DWORD) sspxfer.actSendBuffBytes;
		toSend -= sspxfer.actSendBuffBytes;

		// Transfer complete
		if ((toSend == 0) && (toRecv == 0) || (sspxfer.recvDataOflow == TRUE))
		{
			sspin->recvOflow = sspxfer.recvDataOflow;
			waitLoop = FALSE;
		}
		else
		{
			// Wait for another interrupt to contimue handling
			InterruptDone(pDev->SSPsysIntr);
			rsts = WaitForSingleObject(pDev->sspEvent, 1000);
			if ((rsts == WAIT_TIMEOUT) || (rsts == WAIT_FAILED))
			{
				waitLoop = FALSE;
				sspin->recvOflow = TRUE;
			}
		}
	}

	// Drive the chip select high (if GPIO is used for CS)
	if (pDev->sspNum == 0)
	{
		pDev->pGPIORegs->pio_outp_set = OUTP_STATE_GPIO(5);
	}
	else
	{
		// Not supported on Phytec board
		// TBD Customer will need to implement for their own board
	}

	return TRUE;
}

//------------------------------------------------------------------------------
//
// SSP_PowerDown
//
// Powerdown function
//
extern "C" void SSP_PowerDown(DWORD hDeviceContext)
{
	SSPPeriphDown(hDeviceContext);
}

//------------------------------------------------------------------------------
//
// SSP_PowerUp
//
// Powerup function
//
extern "C" void SSP_PowerUp(DWORD hDeviceContext)
{
	SSPPeriphUp(hDeviceContext);
}

//------------------------------------------------------------------------------
//
// SSP_Deinit
//
// SSP de-init function
//
extern "C" BOOL SSP_Deinit(DWORD hDeviceContext) {
	SSP_DRVCTL_T *pDev = (SSP_DRVCTL_T *) hDeviceContext;

	// Delete SSP BSP class
	if (pDev->pSSPClass != NULL)
	{
		delete pDev->pSSPClass;
		pDev->pSSPClass = NULL;
	}

	if (pDev->pClkPwrRegs != NULL)
	{
		// Disable SSP clock
		SSPPeriphDown(hDeviceContext);

		MmUnmapIoSpace((PVOID) pDev->pClkPwrRegs,
			sizeof (CLKPWR_REGS_T));
		pDev->pClkPwrRegs = NULL;
	}
	if (pDev->pSSPRegs != NULL)
	{
		MmUnmapIoSpace((PVOID) pDev->pSSPRegs,
			sizeof (SSP_REGS_T));
		pDev->pSSPRegs = NULL;
	}
	if (pDev->pGPIORegs != NULL)
	{
		MmUnmapIoSpace((PVOID) pDev->pGPIORegs,
			sizeof (GPIO_REGS_T));
		pDev->pGPIORegs = NULL;
	}

	// Release sysIntr value
	if (pDev->SSPsysIntr != SYSINTR_UNDEFINED)
	{
        KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &pDev->SSPsysIntr, 
            sizeof(pDev->SSPsysIntr), NULL, 0, NULL);
		pDev->SSPsysIntr = SYSINTR_UNDEFINED;
	}

	// Delete event
	if (pDev->sspEvent != NULL)
	{
		CloseHandle(pDev->sspEvent);
		pDev->sspEvent = NULL;
	}

	// Delete access mutex
	if (pDev->sspLock != NULL)
	{
		CloseHandle(pDev->sspLock);
		pDev->sspLock = NULL;
	}

    return TRUE;
}

//------------------------------------------------------------------------------
//
// SSP_Init
//
// SSP Init function
//
extern "C" DWORD SSP_Init(LPCTSTR pContext, LPCVOID lpvBusContext) {
	PHYSICAL_ADDRESS pa;
	UINT32 bytesret, clk;
	int index;
	SSP_DRVCTL_T *pDev;
    HKEY hkey = NULL;
	DWORD dwStatus, dwType, dwSize, indx, irqt, sts = 0;
	WCHAR regkeyname[256];
	SSP_XFER_SETUP_T sspcfg;

    (void) lpvBusContext;

⌨️ 快捷键说明

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