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

📄 i2c_driver.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    dwType = REG_SZ;
    dwStatus = RegQueryValueEx(hkI2C, TEXT("Key"), NULL, &dwType, 
        (LPBYTE) regkeyname, &dwSize);
    if (dwStatus != ERROR_SUCCESS) {
        RETAILMSG(ZONE_ERROR, (_T("IIC_Init: Error getting device key name\r\n")));
	    RegCloseKey(hkI2C);
		goto cleanup;
    }

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

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

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

	// Get IRQ mapped to this I2C channel
	if (index == 0)
	{
		irqt = OAL_INTR_IRQ_I2C_1;
	}
	else
	{
		irqt = OAL_INTR_IRQ_I2C_2;
	}
	pDev = &i2cDrv [index];

	// Setup defaults
	pDev->pI2CRegs = NULL;
	pDev->I2CsysIntr = SYSINTR_UNDEFINED;
	pDev->pClkPwrRegs = NULL;
	pDev->i2cEvent = NULL;
	pDev->i2cLock = NULL;
	pDev->i2cNum = index;

	// Allocate registers for I2C and clock and power
	pa.HighPart = 0;
	pa.LowPart = CLK_PM_BASE;
	pDev->pClkPwrRegs = (CLKPWR_REGS_T *) MmMapIoSpace(pa,
		sizeof (CLKPWR_REGS_T), FALSE);

	pa.HighPart = 0;
	if (index == 0)
	{
		pa.LowPart = I2C1_BASE;
	}
	else
	{
		pa.LowPart = I2C2_BASE;
	}
	pDev->pI2CRegs = (I2C_REGS_T *) MmMapIoSpace(pa,
		sizeof (I2C_REGS_T), FALSE);

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

	// Enable I2C clocking and power for init
	I2CPeriphUp((DWORD) pDev);

	// Allocate I2C and initialize I2C interface
	pDev->pI2CClass = new bspI2C(pDev->pI2CRegs);
	if (pDev->pI2CClass == NULL)
	{
        RETAILMSG(ZONE_ERROR, 
            (TEXT("ERROR: I2C: Failed to allocate I2C driver class\r\n")));
		goto cleanup;
	}

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

        pDev->I2CsysIntr = SYSINTR_UNDEFINED;
        goto cleanup;
    }

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

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

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

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

	pDev->pI2CClass->bspi2cSetClock(clk, 400000, FALSE);
	sts = (DWORD) pDev;

	// Disable I2C clock until it is needed
	I2CPeriphDown((DWORD) pDev);

cleanup:
	return sts;
}

//------------------------------------------------------------------------------
//
// IIC_IOControl
//
// I2C driver general IOCTL handler function
//
extern "C" BOOL IIC_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
                   DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
                   PDWORD pdwActualOut) {
	UINT32 bytesret, clk;
	I2C_XFER_SETUP_T *pi2cSetup;
	I2C_DRVCTL_T *pDev = (I2C_DRVCTL_T *) hOpenContext;

	switch (dwCode)
	{
	case IOCTL_APP_I2CREQ:
        // Attempt transfer
		if ((pBufIn != NULL) && (pBufOut != NULL) &&
			(dwLenIn == sizeof(I2C_OUT_XFER_T)) &&
			(dwLenOut == sizeof(I2C_IN_XFER_T)))
		{
			*pdwActualOut = sizeof(I2C_IN_XFER_T);
            return I2C_Transfer(pDev, (I2C_OUT_XFER_T *) pBufIn,
				(I2C_IN_XFER_T *) pBufOut);
		}
		break;

	case IOCTL_APP_I2CSETUP:
        // Attempt setup
		if ((pBufIn != NULL) && (dwLenIn == sizeof(I2C_XFER_SETUP_T)))
		{
			// Get base clock for I2C
			if (KernelIoControl(IOCTL_LPC32XX_GETHCLK, NULL, 0, &clk,
				sizeof (clk), (LPDWORD) &bytesret) != FALSE)
			{
				pi2cSetup = (I2C_XFER_SETUP_T *) pBufIn;
				I2C_Lock(pDev->i2cLock);
				pDev->pI2CClass->bspi2cSetClock(clk, pi2cSetup->clock,
					pi2cSetup->assym);
				I2C_Unlock(pDev->i2cLock);
				return TRUE;
			}
		}
		break;

	default:
		break;
	}

    return FALSE;
}

//------------------------------------------------------------------------------
//
// IIC_Close
//
// I2C driver close function
//
extern "C" BOOL IIC_Close(DWORD hOpenContext) {
	I2C_DRVCTL_T *pDev = (I2C_DRVCTL_T *) hOpenContext;

	i2cInstances[pDev->i2cNum]--;
	if (i2cInstances[pDev->i2cNum] == 0)
	{
		// Disable clocks, no more I2C channels open
		I2CPeriphDown(hOpenContext);
	}

	return TRUE;
}

//------------------------------------------------------------------------------
//
// IIC_Open
//
// I2C driver open function
//
extern "C" DWORD IIC_Open(DWORD hDeviceContext, DWORD AccessCode,
               DWORD ShareMode) {
	I2C_DRVCTL_T *pDev = (I2C_DRVCTL_T *) hDeviceContext;

    (void) AccessCode;
    (void) ShareMode;

	i2cInstances[pDev->i2cNum]++;
	if (i2cInstances[pDev->i2cNum] == 1)
	{
		// Enable clocks
		I2CPeriphUp(hDeviceContext);
	}

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

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

    /* Read not allowed */
    return 0;
}

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

    /* Write not allowed */
    return 0;
}

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

    /* Seek not allowed */
    return 0;
}


//------------------------------------------------------------------------------
//
// IIC_DLLEntry
//
// DLL entry point
//
extern "C" BOOL __stdcall IIC_DLLEntry (
                             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 + -