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

📄 lpc32xx_otg_i2c.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//

#include "lpc32xx_otg_i2c.h"
#include "bsp.h"

// Static driver data
int LPC32XX_OTGI2C::m_instances = 0;
DWORD LPC32XX_OTGI2C::m_goodinit = 0;
OTGI2C_REGS_T *LPC32XX_OTGI2C::m_pI2CRegs = NULL;
DWORD LPC32XX_OTGI2C::m_I2CsysIntr = SYSINTR_UNDEFINED;
HANDLE LPC32XX_OTGI2C::m_i2cEvent = NULL;
HANDLE LPC32XX_OTGI2C::m_i2cLock = NULL;
class bspI2C *LPC32XX_OTGI2C::m_pI2CClass = NULL;

//********************************************************************
// Initialization and de-init functions
//********************************************************************

// Constructor
LPC32XX_OTGI2C::LPC32XX_OTGI2C(void)
{
	m_instances++;
	if (m_instances == 1)
	{	
		m_goodinit = 0;
	}
}

// Destructor
LPC32XX_OTGI2C::~LPC32XX_OTGI2C(void)
{
	m_instances--;
	if (m_instances == 0)
	{
		Deinit();
		m_goodinit = 0;
	}
}

// Initializes interface
DWORD LPC32XX_OTGI2C::Init(void)
{
	PHYSICAL_ADDRESS pa;
	DWORD irqt, sts = 0;
	UINT32 bytesret, clk;

	if (m_goodinit == 0)
	{
		// Setup defaults
		irqt = OAL_INTR_IRQ_OTG_I2C;
		m_pI2CRegs = NULL;
		m_I2CsysIntr = SYSINTR_UNDEFINED;
		m_i2cEvent = NULL;
		m_i2cLock = NULL;

		// Allocate registers for I2C
		pa.QuadPart = OTG_I2C_BASE;
		m_pI2CRegs = (OTGI2C_REGS_T *) MmMapIoSpace(pa,
			sizeof (OTGI2C_REGS_T), FALSE);
		if (m_pI2CRegs == NULL)
		{
		    RETAILMSG(ZONE_ERROR, 
			    (TEXT("ERROR: OTGI2C: Failed to map registers\r\n")));
			goto cleanup;
		}

		// Allocate I2C and initialize I2C interface
		m_pI2CClass = new bspI2C((I2C_REGS_T *) m_pI2CRegs);
		if (m_pI2CClass == NULL)
		{
		    RETAILMSG(ZONE_ERROR, 
			    (TEXT("ERROR: OTGI2C: Failed to allocate I2C driver class\r\n")));
			goto cleanup;
		}

		// Get sysintr value
		if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irqt, sizeof(irqt),
			&m_I2CsysIntr, sizeof(m_I2CsysIntr), NULL))
	    {
		    RETAILMSG(ZONE_ERROR, 
			    (TEXT("ERROR: OTGI2C: Failed to request the I2C sysintr.\r\n")));
	        m_I2CsysIntr = SYSINTR_UNDEFINED;
		    goto cleanup;
	    }

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

		// Initialize the I2C interrupt
		if (InterruptInitialize(m_I2CsysIntr, m_i2cEvent,
			NULL, 0) == FALSE) {
			// Cannot initialize interrupt
		    RETAILMSG(ZONE_ERROR, 
				(TEXT("ERROR: OTGI2C: Cannot initialize I2C interrupt\r\n")));
	        goto cleanup;
		}
		InterruptDone(m_I2CsysIntr);

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

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

		m_pI2CClass->bspi2cSetClock(clk, 100000, FALSE);
		m_goodinit = 1;
	}

cleanup:
	if (m_goodinit == 0)
	{
		Deinit();
	}
	return m_goodinit;
}

// Re-initializes interface
//void LPC32XX_OTGI2C::Reinit(void)
//{ // tbd
	// Nothing to do...yet
//}

// De-initialize driver
void LPC32XX_OTGI2C::Deinit(void)
{
	if (m_i2cEvent != NULL)
	{
		CloseHandle(m_i2cEvent);
		m_i2cEvent = NULL;
	}
	if (m_I2CsysIntr != SYSINTR_UNDEFINED)
	{
		KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &m_I2CsysIntr,
			sizeof(m_I2CsysIntr), NULL, 0, NULL);
		m_I2CsysIntr = SYSINTR_UNDEFINED;
	}
	if (m_pI2CClass != NULL)
	{
		delete m_pI2CClass;
		m_pI2CClass = NULL;
	}
	if (m_pI2CRegs != NULL)
	{
		MmUnmapIoSpace(m_pI2CRegs, sizeof(OTGI2C_REGS_T));
		m_pI2CRegs = NULL;
	}
}

//********************************************************************
// I2C data read and write functions
//********************************************************************

// Perform a read of the OTG device via I2C
DWORD LPC32XX_OTGI2C::ReadReg(UINT8 reg,
							  UINT8 *buff,
							  int bytes)
{
	DWORD good;
	I2C_OUT_XFER_T xferout;
	I2C_IN_XFER_T xferin;

	// Setup transfer
	xferout.flags_buff [0] = (OTG_DEV_ADDR | I2C_WRITE | I2C_START_FLAG);
	xferout.flags_buff [1] = reg;

	// Start read operation with repeated start
	xferout.flags_buff [2] = (OTG_DEV_ADDR | I2C_READ | I2C_START_FLAG);

	// Read bytes, send 3 bytes
	xferout.tosend = 3;
	xferout.torecv = bytes;

	good = I2CTransaction(&xferout, &xferin);
	if (good != 0)
	{
		if (xferin.ist != I2CST_COMPLETE)
		{
			good = 0;
		}
		else
		{
			memcpy(buff, xferin.buff, bytes);
		}
	}

	if (bytes == 1)
	{
		DEBUGMSG(1, (L"LPC32XX_OTGI2C::ReadReg 0x%x = 0x%x\r\n", reg, *buff));
	}
	else
	{
		UINT16 tmp = *buff + (*(buff + 1) << 8);
		DEBUGMSG(1, (L"LPC32XX_OTGI2C::ReadReg 0x%x = 0x%x\r\n", reg, tmp));
	}

	return good;
}

// Perform a write on the OTG device via I2C
DWORD LPC32XX_OTGI2C::WriteReg(UINT8 reg,
							   UINT8 *buff,
							   int bytes)
{
	DWORD good;
	I2C_OUT_XFER_T xferout;
	I2C_IN_XFER_T xferin;
	int nidx;

DEBUGMSG(1, (L"LPC32XX_OTGI2C::WriteReg 0x%x = 0x%x (%d)\r\n", reg, *buff, bytes));

	// Setup transfer
	xferout.flags_buff [0] = (OTG_DEV_ADDR | I2C_WRITE | I2C_START_FLAG);
	xferout.flags_buff [1] = reg;

	// Send bytes, read 0 bytes
	xferout.tosend = 2 + bytes;
	xferout.torecv = 0;

	// Start read operation with repeated start
	nidx = 2;
	while (bytes > 1)
	{
		xferout.flags_buff [nidx] = buff[nidx - 2];
		nidx++;
		bytes--;
	}
	xferout.flags_buff [nidx] = (buff[nidx - 2] | I2C_STOP_FLAG);

	good = I2CTransaction(&xferout, &xferin);
	if (good != 0)
	{
		if (xferin.ist != I2CST_COMPLETE)
		{
			good = 0;
		}
	}

	return good;
}

//********************************************************************
// I2C data read and write function
//********************************************************************

// Perform a transaction on the OTG device via I2C
DWORD LPC32XX_OTGI2C::I2CTransaction(I2C_OUT_XFER_T *pI2COut,
									 I2C_IN_XFER_T *pI2CIn)
{
	I2C_ST_T ist;
	DWORD rsts, xg = 0;
	BOOL xcomp;
	INT32 sendBytes = pI2COut->tosend;

	I2C_Lock();

	// Clear sysIntr
	ResetEvent(m_i2cEvent);

	pI2CIn->recvBytes = 0;

	// Timeout failure?
	if (WaitForSingleObject(m_i2cEvent, 0) != WAIT_FAILED)
	{
		// Start transfer
		xcomp = FALSE;
		if (m_pI2CClass->bspi2cStartXfer(pI2COut->flags_buff,
			pI2COut->tosend, pI2COut->torecv) == FALSE)
		{
			xcomp = TRUE;
		}

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

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

			InterruptDone(m_I2CsysIntr);
		}

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

			// Copy bytes
			pI2CIn->recvBytes =
				m_pI2CClass->bspI2CGetData(pI2CIn->buff, 32);
		}
	}

	I2C_Unlock();

	return xg;
}

//********************************************************************
// OTG I2C driver internal functions
//********************************************************************

//  Lock I2C access
void LPC32XX_OTGI2C::I2C_Lock(void)
{
	WaitForSingleObject(m_i2cLock, 150);
}

//  Unlock I2C accesss
void LPC32XX_OTGI2C::I2C_Unlock(void)
{
	ReleaseMutex(m_i2cLock);
}

⌨️ 快捷键说明

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