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

📄 i2c_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
//*********************************************************************
//
// i2c_driver.cpp
//
// General I2C DLL
//

#include <windows.h>
#include <nkintr.h>
#include <CEDDK.h>
#include "bsp.h"
#include "bsp_i2c.h"
#include "drv_ioctl_funcs.h"
#include "lpc32xx_i2c.h"
#include "lpc32xx_clkpwr.h"

//------------------------------------------------------------------------------
// I2C allocation for the Phytec LPC3250 board
// I2C1 (3.0v)
//   I2S codec
//   LCD (not connected)
//   RTC
// I2C2 (1.8v)
//   Not used
//------------------------------------------------------------------------------

// Device context instance
typedef struct
{
	I2C_REGS_T *pI2CRegs;
	CLKPWR_REGS_T *pClkPwrRegs; // Poiner to CLKPWR regs
	DWORD I2CsysIntr;           // SysIntr value for device
	HANDLE i2cEvent;            // Interrupt event handler
	HANDLE i2cLock;             // Mutex for I2C access lock
	int    i2cNum;              // 0 for I2C1, 1 for I2C2
	class bspI2C *pI2CClass;    // Allocated I2C control class
} I2C_DRVCTL_T;
static I2C_DRVCTL_T i2cDrv[3] = {
	{NULL, NULL, SYSINTR_UNDEFINED, NULL, NULL, 0, NULL},  // I2C1
	{NULL, NULL, SYSINTR_UNDEFINED, NULL, NULL, 2, NULL}}; // I2C2

// Number of open instances
static int i2cInstances[3] = {0, 0, 0};

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

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

//------------------------------------------------------------------------------
//
// I2CPeriphDown
//
// Disables clocking and power state
//
static void I2CPeriphDown(DWORD hDeviceContext)
{
	volatile UINT32 tmp;
	I2C_DRVCTL_T *pDev = (I2C_DRVCTL_T *) hDeviceContext;

	// Disable I2C clock
	tmp = pDev->pClkPwrRegs->clkpwr_i2c_clk_ctrl;
	if (pDev->i2cNum == 0)
	{
		pDev->pClkPwrRegs->clkpwr_i2c_clk_ctrl = tmp &
			~CLKPWR_I2CCLK_I2C1CLK_EN;
	}
	else
	{
		pDev->pClkPwrRegs->clkpwr_i2c_clk_ctrl = tmp &
			~CLKPWR_I2CCLK_I2C2CLK_EN;
	}
}

//------------------------------------------------------------------------------
//
// I2CPeriphUp
//
// Enables peripheral clocking and power state
//
extern "C" void I2CPeriphUp(DWORD hDeviceContext)
{
	volatile UINT32 tmp;
	I2C_DRVCTL_T *pDev = (I2C_DRVCTL_T *) hDeviceContext;

	// Enable I2C clock and pullup mode
	tmp = pDev->pClkPwrRegs->clkpwr_i2c_clk_ctrl;
	if (pDev->i2cNum == 0)
	{
		pDev->pClkPwrRegs->clkpwr_i2c_clk_ctrl =
			tmp | CLKPWR_I2CCLK_I2C1CLK_EN | CLKPWR_I2CCLK_I2C2HI_DRIVE;
	}
	else
	{
		tmp = tmp & ~CLKPWR_I2CCLK_I2C2HI_DRIVE;
		pDev->pClkPwrRegs->clkpwr_i2c_clk_ctrl =
			tmp | CLKPWR_I2CCLK_I2C2CLK_EN;
	}
}

//------------------------------------------------------------------------------
//
// I2C_Transfer
//
// I2C transaction handler, handles both RX and TX for a specific channel
//
static BOOL I2C_Transfer(I2C_DRVCTL_T *pI2cDrv,
						 I2C_OUT_XFER_T *i2cout,
						 I2C_IN_XFER_T *i2cin)
{
	I2C_ST_T ist;
	DWORD rsts;
	BOOL xcomp, xg = FALSE;
	INT32 sendBytes = i2cout->tosend;

	I2C_Lock(pI2cDrv->i2cLock);

	// Clear sysIntr
	ResetEvent(pI2cDrv->i2cEvent);

	i2cin->recvBytes = 0;

	// Timeout failure?
	if (WaitForSingleObject(pI2cDrv->i2cEvent, 0) != WAIT_FAILED)
	{
		// Start transfer
		xcomp = FALSE;
		if (pI2cDrv->pI2CClass->bspi2cStartXfer(i2cout->flags_buff,
			i2cout->tosend, i2cout->torecv) == FALSE)
		{
			xcomp = TRUE;
		}

		// Loop until transfer complete
		while (xcomp == FALSE)
		{
			// Wait for interrupt
			rsts = WaitForSingleObject(pI2cDrv->i2cEvent, 250);
			if (rsts == WAIT_TIMEOUT)
			{
				xcomp = TRUE;
				while (1);
			}
			else if (rsts == WAIT_FAILED)
			{
				xcomp = TRUE;
				while (1);
			}
			else
			{
				// Handle interrupt
				ist = pI2cDrv->pI2CClass->bspi2cInt();

				// Exit if no longet active
				if (ist != I2CST_ACTIVE)
				{
					xcomp = TRUE;
				}
			}

			InterruptDone(pI2cDrv->I2CsysIntr);
		}

		// Check transfer status and copy RX bytes if needed
		i2cin->ist = pI2cDrv->pI2CClass->bspi2cGetStatus();
		if (i2cin->ist == I2CST_COMPLETE)
		{
			xg = TRUE;

			// Copy bytes
			i2cin->recvBytes =
				pI2cDrv->pI2CClass->bspI2CGetData(i2cin->buff, 32);
		}
	}

	I2C_Unlock(pI2cDrv->i2cLock);

	return xg;
}

//------------------------------------------------------------------------------
//
// IIC_PowerDown
//
// Stub function for powerdown
//
extern "C" void IIC_PowerDown(DWORD hDeviceContext)
{
	// Do nothing, system power management for I2C is handled in the kernel
	// power down or OTG functions, as other system drivers may require the
	// I2C DLL to correctly work for their power down functions.
}

//------------------------------------------------------------------------------
//
// IIC_PowerUp
//
// Stub function for powerup
//
extern "C" void IIC_PowerUp(DWORD hDeviceContext)
{
	// Do nothing, handled in kernel power up or OTG functions
}

//------------------------------------------------------------------------------
//
// IIC_Deinit
//
// I2C de-init function
//
extern "C" BOOL IIC_Deinit(DWORD hDeviceContext)
{
	I2C_DRVCTL_T *pDev = (I2C_DRVCTL_T *) hDeviceContext;

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

		MmUnmapIoSpace((PVOID) pDev->pClkPwrRegs,
			sizeof (CLKPWR_REGS_T));
		pDev->pClkPwrRegs = NULL;
	}
	if (pDev->pI2CRegs != NULL)
	{
		if (pDev->pI2CClass != NULL)
		{
			delete pDev->pI2CClass;
			pDev->pI2CClass = NULL;
		}

		MmUnmapIoSpace((PVOID) pDev->pI2CRegs,
			sizeof (I2C_REGS_T));
		pDev->pI2CRegs = NULL;
	}

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

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

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

    return TRUE;
}

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

    (void) lpvBusContext;

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

	// Get key value
    dwSize = sizeof(regkeyname);

⌨️ 快捷键说明

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