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

📄 ssp_driver.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	DEBUGMSG(ZONE_INIT,
		(_T("SSP_IOCTL ID IOCTL_APP_SSPREQ = %x\r\n"), IOCTL_APP_SSPREQ));
	DEBUGMSG(ZONE_INIT,
		(_T("SSP_IOCTL ID IOCTL_APP_SSPSETUP = %x\r\n"), IOCTL_APP_SSPSETUP));

	// Open the registry key and read the key value
    dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pContext, 0, 0, &hkey);
    if (dwStatus != ERROR_SUCCESS) {
        RETAILMSG(ZONE_ERROR, (_T("SSP_Init: Error opening device registry!\r\n")));
		goto cleanup;
    }

	// Get key value
    dwSize = sizeof(regkeyname);
    dwType = REG_SZ;
    dwStatus = RegQueryValueEx(hkey, TEXT("Key"), NULL, &dwType, 
        (LPBYTE) regkeyname, &dwSize);
    if (dwStatus != ERROR_SUCCESS) {
        RETAILMSG(ZONE_ERROR, (_T("SSP_Init: Error getting device key name\r\n")));
	    RegCloseKey(hkey);
		goto cleanup;
    }

	// Open the registry key and read the index value
    dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkeyname, 0, 0, &hkey);
    if (dwStatus != ERROR_SUCCESS) {
        RETAILMSG(ZONE_ERROR, (_T("SSP_Init: Error opening device registry!\r\n")));
		goto cleanup;
    }

	// Get SSP index value
    dwSize = sizeof(indx);
    dwType = REG_DWORD;
    dwStatus = RegQueryValueEx(hkey, TEXT("Index"), NULL, &dwType, 
        (LPBYTE) &indx, &dwSize);
    if (dwStatus != ERROR_SUCCESS) {
        RETAILMSG(ZONE_ERROR, (_T("SSP_Init: Error getting Index\r\n")));
    }
	index = (int) indx;

    RegCloseKey(hkey);
    DEBUGMSG(ZONE_INIT, (_T("SSP_Init: Using index %d\r\n"), index));

	// Get IRQ mapped to this SSP channel
	if (index == 0)
	{
		irqt = OAL_INTR_IRQ_SSP0;
	}
	else
	{
		irqt = OAL_INTR_IRQ_SSP1;
	}
	pDev = &sspDrv [index];

	// Setup defaults
	pDev->pSSPRegs = NULL;
	pDev->pClkPwrRegs = NULL;
	pDev->pGPIORegs = NULL;
	pDev->SSPsysIntr = SYSINTR_UNDEFINED;
	pDev->sspEvent = NULL;
	pDev->sspLock = NULL;
	pDev->sspNum = index;

	// Allocate registers for SSP, clock and power, and GPIO
	pa.QuadPart = CLK_PM_BASE;
	pDev->pClkPwrRegs = (CLKPWR_REGS_T *) MmMapIoSpace(pa,
		sizeof (CLKPWR_REGS_T), FALSE);

	// SSP 0 or 1
	if (index == 0)
	{
		pa.QuadPart = SSP0_BASE;
	}
	else
	{
		pa.QuadPart = SSP1_BASE;
	}
	pDev->pSSPRegs = (SSP_REGS_T *) MmMapIoSpace(pa,
		sizeof (SSP_REGS_T), FALSE);

	// GPIO
	pa.QuadPart = GPIO_BASE;
	pDev->pGPIORegs = (GPIO_REGS_T *) MmMapIoSpace(pa,
		sizeof (GPIO_REGS_T), FALSE);

	if ((pDev->pClkPwrRegs == NULL) || (pDev->pGPIORegs == NULL) ||
		(pDev->pSSPRegs == NULL))
	{
        RETAILMSG(ZONE_ERROR, 
            (TEXT("SSP_Init: Failed to map registers\r\n")));
		goto cleanup;
	}

	// Setup muxing for this peripheral
	if (index == 0)
	{
		// Setup GPIO as an output for SSP0 CS
		pDev->pGPIORegs->pio_mux_clr = PIO1_GPIO05_SSEL0;
		pDev->pGPIORegs->pio_dir_set = OUTP_STATE_GPIO(5);
		pDev->pGPIORegs->pio_outp_set = OUTP_STATE_GPIO(5);

		// The MISO, MOSI, and SCK signals are controlled by SSP0
		pDev->pGPIORegs->pio_mux2_set = (PIO2_SPI1DATAIO_SSP0_MOSI |
			PIO2_SPI1DATAIN_SSP0_MISO | PIO2_SPI1CLK_SCK0);
	}
	else
	{
		// Not supported on Phytec board
		// TBD Customer will need to implement for their own board
	}

	// Enable SSP clocking and power for init
	SSPPeriphUp((DWORD) pDev);

	// Get base clock for SSP
	if (KernelIoControl(IOCTL_LPC32XX_GETHCLK, NULL, 0, &clk,
		sizeof (clk), (LPDWORD) &bytesret) == FALSE)
	{
		// Cannot get clock
        RETAILMSG(ZONE_ERROR, 
            (TEXT("SSP_Init: Error getting SSP base clock rate.\r\n")));
		goto cleanup;
	}

	// Allocate SSP and initialize SSP interface
	pDev->pSSPClass = new bspssp(pDev->pSSPRegs, pDev->pClkPwrRegs, pDev->sspNum);
	if (pDev->pSSPClass == NULL)
	{
        RETAILMSG(ZONE_ERROR, 
            (TEXT("SSP_Init: Failed to allocate SSP driver class\r\n")));
		goto cleanup;
	}

	// Get sysintr value
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irqt, sizeof(irqt),
		&pDev->SSPsysIntr, sizeof(pDev->SSPsysIntr), NULL))
    {
        RETAILMSG(ZONE_ERROR, 
            (TEXT("SSP_Init: Failed to request the SSP sysintr.\r\n")));

        pDev->SSPsysIntr = SYSINTR_UNDEFINED;
        goto cleanup;
    }

	// Create event handle
	pDev->sspEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (pDev->sspEvent == NULL)
	{
        RETAILMSG(ZONE_ERROR, 
            (TEXT("SSP_Init: Failed to create handler event.\r\n")));
		goto cleanup;
	}

	// Initialize the SSP interrupt
	if (InterruptInitialize(pDev->SSPsysIntr, pDev->sspEvent,
		NULL, 0) == FALSE) {
		// Cannot initialize interrupt
        RETAILMSG(ZONE_ERROR, 
			(TEXT("SSP_Init: Cannot initialize SSP interrupt\r\n")));
        goto cleanup;
	}
	InterruptDone(pDev->SSPsysIntr);

	// Create access mutex for SSP registers
	pDev->sspLock = CreateMutex(NULL, FALSE, NULL);
	if (pDev->sspLock == NULL) {
        RETAILMSG(ZONE_ERROR,
			(TEXT("SSP_Init: Error creating control mutex\r\n")));
		goto cleanup;
	}

	// Setup for 8 bit transfers, 100K clock, locked CS
    sspcfg.databits = 8;
    sspcfg.mode = SSP_CR0_FRF_MOT;
    sspcfg.highclkSpiFrames = FALSE;
    sspcfg.usesecondClkSpi = FALSE;
    sspcfg.sspClk = 100000;
    sspcfg.masterMode = TRUE;
	pDev->pSSPClass->bspsspSetup(clk, &sspcfg);
	sts = (DWORD) pDev;

	// Disable SSP clock until it is needed
	SSPPeriphDown((DWORD) pDev);

cleanup:
	return sts;
}

//------------------------------------------------------------------------------
//
// SSP_IOControl
//
// SSP driver general IOCTL handler function
//
extern "C" BOOL SSP_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
                   DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
                   PDWORD pdwActualOut) {
	UINT32 bytesret, clk;
	SSP_XFER_SETUP_T *psspSetup;
	SSP_DRVCTL_T *pDev = (SSP_DRVCTL_T *) hOpenContext;

	switch (dwCode)
	{
	case IOCTL_APP_SSPREQ:
        // Attempt transfer
		if ((pBufIn != NULL) && (pBufOut != NULL) &&
			(dwLenIn == sizeof(SSP_SEND_XFER_T)) &&
			(dwLenOut == sizeof(SSP_RECV_XFER_T)))
		{
			*pdwActualOut = sizeof(SSP_SEND_XFER_T);
            return SSP_Transfer(pDev, (SSP_SEND_XFER_T *) pBufIn,
				(SSP_RECV_XFER_T *) pBufOut);
		}
		break;

	case IOCTL_APP_SSPSETUP:
        // Attempt setup
		if ((pBufIn != NULL) && (dwLenIn == sizeof(SSP_XFER_SETUP_T)))
		{
			// Get base clock for SSP
			if (KernelIoControl(IOCTL_LPC32XX_GETHCLK, NULL, 0, &clk,
				sizeof (clk), (LPDWORD) &bytesret) != FALSE)
			{
				psspSetup = (SSP_XFER_SETUP_T *) pBufIn;
				SSP_Lock(pDev->sspLock);
				pDev->pSSPClass->bspsspSetup(clk, psspSetup);

				// Also setup GPIO if needed
				SSP_CS_Setup(pDev, psspSetup->csLocked);

				SSP_Unlock(pDev->sspLock);
				return TRUE;
			}
		}
		break;

	default:
		break;
	}

    return FALSE;
}

//------------------------------------------------------------------------------
//
// SSP_Close
//
// SSP driver close function
//
extern "C" BOOL SSP_Close(DWORD hOpenContext) {
	SSP_DRVCTL_T *pDev = (SSP_DRVCTL_T *) hOpenContext;

	sspInstances[pDev->sspNum]--;
	if (sspInstances[pDev->sspNum] == 0)
	{
		// Disable clocks, no more SSP channels open
		SSPPeriphDown(hOpenContext);
	}

	return TRUE;
}

//------------------------------------------------------------------------------
//
// SSP_Open
//
// SSP driver open function
//
extern "C" DWORD SSP_Open(DWORD hDeviceContext, DWORD AccessCode,
               DWORD ShareMode) {
	SSP_DRVCTL_T *pDev = (SSP_DRVCTL_T *) hDeviceContext;

    (void) AccessCode;
    (void) ShareMode;

	sspInstances[pDev->sspNum]++;
	if (sspInstances[pDev->sspNum] == 1)
	{
		// Enable clocks
		SSPPeriphUp(hDeviceContext);
	}

	// Return the device context, this will be used as the open
	// context to identify which SSP channel is used for operations
    return hDeviceContext;
}

//------------------------------------------------------------------------------
//
// SSP_Read
//
// SSP driver read stub function
//
extern "C" DWORD SSP_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count) {
    (void) hOpenContext;
    (void) pBuffer;
    (void) Count;

    /* Read not allowed */
    return 0;
}

//------------------------------------------------------------------------------
//
// SSP_Write
//
// SSP driver write stub function
//
extern "C" DWORD SSP_Write(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count) {
    (void) hOpenContext;
    (void) pBuffer;
    (void) Count;

    /* Write not allowed */
    return 0;
}

//------------------------------------------------------------------------------
//
// SSP_Seek
//
// SSP driver seek stub function
//
extern "C" DWORD SSP_Seek(DWORD hOpenContext, long Amount, WORD Type) {
    (void) hOpenContext;
    (void) Amount;
    (void) Type;

    /* Seek not allowed */
    return 0;
}

//------------------------------------------------------------------------------
//
// DllMain
//
// SSP DLL entry point
//
extern "C" BOOL __stdcall DllMain (
                             HANDLE  hinstDLL,      // [in] : Instance pointer
                             DWORD   Op,                // [in] : Reason routine is called
                             LPVOID  lpvReserved        // [in] : system parameter
                             )
{
	switch(Op) {
    case DLL_PROCESS_ATTACH :
        DisableThreadLibraryCalls((HMODULE) hinstDLL);
        break;
        
    case DLL_PROCESS_DETACH :
        break;
        
    case DLL_THREAD_DETACH :
    case DLL_THREAD_ATTACH :
        break;
        
    default :
        break;
    }
    return TRUE;
}

⌨️ 快捷键说明

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