Merge branch 'master' of github.com:p42/project42
This commit is contained in:
commit
0709d52b3a
706
core/i2c/i2c.c
706
core/i2c/i2c.c
|
@ -1,353 +1,353 @@
|
|||
/*****************************************************************************
|
||||
* i2c.c: I2C C file for NXP LPC11xx/13xx Family Microprocessors
|
||||
*
|
||||
* Copyright(C) 2008, NXP Semiconductor
|
||||
* Parts of this code are (C) 2010, MyVoice CAD/CAM Services
|
||||
* All rights reserved.
|
||||
*
|
||||
* History
|
||||
* 2009.12.07 ver 1.00 Preliminary version, first Release
|
||||
* 2010.07.19 ver 1.10 Rob Jansen - MyVoice CAD/CAM Services:
|
||||
* Major cleaning and a rewrite of some functions
|
||||
* - adding ACK/NACK handling to the state machine
|
||||
* - adding a return result to the I2CEngine()
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "i2c.h"
|
||||
|
||||
volatile uint32_t I2CMasterState = I2CSTATE_IDLE;
|
||||
volatile uint32_t I2CSlaveState = I2CSTATE_IDLE;
|
||||
|
||||
volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
|
||||
volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
|
||||
volatile uint32_t I2CReadLength;
|
||||
volatile uint32_t I2CWriteLength;
|
||||
|
||||
volatile uint32_t RdIndex = 0;
|
||||
volatile uint32_t WrIndex = 0;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2C_IRQHandler
|
||||
**
|
||||
** Descriptions: I2C interrupt handler, deal with master mode only.
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: None
|
||||
**
|
||||
*****************************************************************************/
|
||||
void I2C_IRQHandler(void)
|
||||
{
|
||||
uint8_t StatValue;
|
||||
|
||||
/* this handler deals with master read and master write only */
|
||||
StatValue = I2C_I2CSTAT;
|
||||
switch ( StatValue )
|
||||
{
|
||||
case 0x08:
|
||||
/*
|
||||
* A START condition has been transmitted.
|
||||
* We now send the slave address and initialize
|
||||
* the write buffer
|
||||
* (we always start with a write after START+SLA)
|
||||
*/
|
||||
WrIndex = 0;
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
|
||||
I2CMasterState = I2CSTATE_PENDING;
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
/*
|
||||
* A repeated START condition has been transmitted.
|
||||
* Now a second, read, transaction follows so we
|
||||
* initialize the read buffer.
|
||||
*/
|
||||
RdIndex = 0;
|
||||
/* Send SLA with R bit set, */
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
|
||||
break;
|
||||
|
||||
case 0x18:
|
||||
/*
|
||||
* SLA+W has been transmitted; ACK has been received.
|
||||
* We now start writing bytes.
|
||||
*/
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
/*
|
||||
* SLA+W has been transmitted; NOT ACK has been received.
|
||||
* Send a stop condition to terminate the transaction
|
||||
* and signal I2CEngine the transaction is aborted.
|
||||
*/
|
||||
I2C_I2CCONSET = I2CONSET_STO;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
I2CMasterState = I2CSTATE_SLA_NACK;
|
||||
break;
|
||||
|
||||
case 0x28:
|
||||
/*
|
||||
* Data in I2DAT has been transmitted; ACK has been received.
|
||||
* Continue sending more bytes as long as there are bytes to send
|
||||
* and after this check if a read transaction should follow.
|
||||
*/
|
||||
if ( WrIndex < I2CWriteLength )
|
||||
{
|
||||
/* Keep writing as long as bytes avail */
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( I2CReadLength != 0 )
|
||||
{
|
||||
/* Send a Repeated START to initialize a read transaction */
|
||||
/* (handled in state 0x10) */
|
||||
I2C_I2CCONSET = I2CONSET_STA; /* Set Repeated-start flag */
|
||||
}
|
||||
else
|
||||
{
|
||||
I2CMasterState = I2CSTATE_ACK;
|
||||
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||
}
|
||||
}
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
/*
|
||||
* Data byte in I2DAT has been transmitted; NOT ACK has been received
|
||||
* Send a STOP condition to terminate the transaction and inform the
|
||||
* I2CEngine that the transaction failed.
|
||||
*/
|
||||
I2C_I2CCONSET = I2CONSET_STO;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
I2CMasterState = I2CSTATE_NACK;
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
/*
|
||||
* Arbitration loss in SLA+R/W or Data bytes.
|
||||
* This is a fatal condition, the transaction did not complete due
|
||||
* to external reasons (e.g. hardware system failure).
|
||||
* Inform the I2CEngine of this and cancel the transaction
|
||||
* (this is automatically done by the I2C hardware)
|
||||
*/
|
||||
I2CMasterState = I2CSTATE_ARB_LOSS;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
/*
|
||||
* SLA+R has been transmitted; ACK has been received.
|
||||
* Initialize a read.
|
||||
* Since a NOT ACK is sent after reading the last byte,
|
||||
* we need to prepare a NOT ACK in case we only read 1 byte.
|
||||
*/
|
||||
if ( I2CReadLength == 1 )
|
||||
{
|
||||
/* last (and only) byte: send a NACK after data is received */
|
||||
I2C_I2CCONCLR = I2CONCLR_AAC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* more bytes to follow: send an ACK after data is received */
|
||||
I2C_I2CCONSET = I2CONSET_AA;
|
||||
}
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x48:
|
||||
/*
|
||||
* SLA+R has been transmitted; NOT ACK has been received.
|
||||
* Send a stop condition to terminate the transaction
|
||||
* and signal I2CEngine the transaction is aborted.
|
||||
*/
|
||||
I2C_I2CCONSET = I2CONSET_STO;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
I2CMasterState = I2CSTATE_SLA_NACK;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
/*
|
||||
* Data byte has been received; ACK has been returned.
|
||||
* Read the byte and check for more bytes to read.
|
||||
* Send a NOT ACK after the last byte is received
|
||||
*/
|
||||
I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
|
||||
if ( RdIndex < (I2CReadLength-1) )
|
||||
{
|
||||
/* lmore bytes to follow: send an ACK after data is received */
|
||||
I2C_I2CCONSET = I2CONSET_AA;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* last byte: send a NACK after data is received */
|
||||
I2C_I2CCONCLR = I2CONCLR_AAC;
|
||||
}
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x58:
|
||||
/*
|
||||
* Data byte has been received; NOT ACK has been returned.
|
||||
* This is the last byte to read.
|
||||
* Generate a STOP condition and flag the I2CEngine that the
|
||||
* transaction is finished.
|
||||
*/
|
||||
I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
|
||||
I2CMasterState = I2CSTATE_ACK;
|
||||
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CStart
|
||||
**
|
||||
** Descriptions: Create I2C start condition, a timeout
|
||||
** value is set if the I2C never gets started,
|
||||
** and timed out. It's a fatal error.
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: true or false, return false if timed out
|
||||
**
|
||||
*****************************************************************************/
|
||||
static uint32_t I2CStart( void )
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
|
||||
/*--- Issue a start condition ---*/
|
||||
I2C_I2CCONSET = I2CONSET_STA; /* Set Start flag */
|
||||
|
||||
while((I2CMasterState != I2CSTATE_PENDING) && (timeout < MAX_TIMEOUT))
|
||||
{
|
||||
timeout++;
|
||||
}
|
||||
|
||||
return (timeout < MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CStop
|
||||
**
|
||||
** Descriptions: Set the I2C stop condition
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: true or never return
|
||||
**
|
||||
*****************************************************************************/
|
||||
static uint32_t I2CStop( void )
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
|
||||
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
|
||||
|
||||
/*--- Wait for STOP detected ---*/
|
||||
while((I2C_I2CCONSET & I2CONSET_STO) && (timeout < MAX_TIMEOUT))
|
||||
{
|
||||
timeout++;
|
||||
}
|
||||
return (timeout >= MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CInit
|
||||
**
|
||||
** Descriptions: Initialize I2C controller
|
||||
**
|
||||
** parameters: I2c mode is either MASTER or SLAVE
|
||||
** Returned value: true or false, return false if the I2C
|
||||
** interrupt handler was not installed correctly
|
||||
**
|
||||
*****************************************************************************/
|
||||
uint32_t i2cInit( uint32_t I2cMode )
|
||||
{
|
||||
SCB_PRESETCTRL |= (0x1<<1);
|
||||
|
||||
// Enable I2C clock
|
||||
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_I2C);
|
||||
|
||||
// Configure pin 0.4 for SCL
|
||||
IOCON_PIO0_4 &= ~(IOCON_PIO0_4_FUNC_MASK | IOCON_PIO0_4_I2CMODE_MASK);
|
||||
IOCON_PIO0_4 |= (IOCON_PIO0_4_FUNC_I2CSCL);
|
||||
|
||||
// Configure pin 0.5 for SDA
|
||||
IOCON_PIO0_5 &= ~(IOCON_PIO0_5_FUNC_MASK | IOCON_PIO0_5_I2CMODE_MASK);
|
||||
IOCON_PIO0_5 |= IOCON_PIO0_5_FUNC_I2CSDA;
|
||||
|
||||
// Clear flags
|
||||
I2C_I2CCONCLR = I2C_I2CCONCLR_AAC |
|
||||
I2C_I2CCONCLR_SIC |
|
||||
I2C_I2CCONCLR_STAC |
|
||||
I2C_I2CCONCLR_I2ENC;
|
||||
|
||||
// See p.128 for appropriate values for SCLL and SCLH
|
||||
#if I2C_FAST_MODE_PLUS
|
||||
IOCON_PIO0_4 |= (IOCON_PIO0_4_I2CMODE_FASTPLUSI2C);
|
||||
IOCON_PIO0_5 |= (IOCON_PIO0_5_I2CMODE_FASTPLUSI2C);
|
||||
I2C_I2CSCLL = I2C_SCLL_HS_SCLL;
|
||||
I2C_I2CSCLH = I2C_SCLH_HS_SCLH;
|
||||
#else
|
||||
I2C_I2CSCLL = I2SCLL_SCLL;
|
||||
I2C_I2CSCLH = I2SCLH_SCLH;
|
||||
#endif
|
||||
|
||||
if ( I2cMode == I2CSLAVE )
|
||||
{
|
||||
I2C_I2CADR0 = SLAVE_ADDR;
|
||||
}
|
||||
|
||||
/* Enable the I2C Interrupt */
|
||||
NVIC_EnableIRQ(I2C_IRQn);
|
||||
I2C_I2CCONSET = I2C_I2CCONSET_I2EN;
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CEngine
|
||||
**
|
||||
** Descriptions: The routine to complete a I2C transaction
|
||||
** from start to stop. All the intermitten
|
||||
** steps are handled in the interrupt handler.
|
||||
** Before this routine is called, the read
|
||||
** length, write length and I2C master buffer
|
||||
** need to be filled.
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: Any of the I2CSTATE_... values. See i2c.h
|
||||
**
|
||||
*****************************************************************************/
|
||||
uint32_t i2cEngine( void )
|
||||
{
|
||||
I2CMasterState = I2CSTATE_IDLE;
|
||||
RdIndex = 0;
|
||||
WrIndex = 0;
|
||||
if ( I2CStart() != TRUE )
|
||||
{
|
||||
I2CStop();
|
||||
return ( FALSE );
|
||||
}
|
||||
|
||||
/* wait until the state is a terminal state */
|
||||
while (I2CMasterState < 0x100);
|
||||
|
||||
return ( I2CMasterState );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
** End Of File
|
||||
******************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* i2c.c: I2C C file for NXP LPC11xx/13xx Family Microprocessors
|
||||
*
|
||||
* Copyright(C) 2008, NXP Semiconductor
|
||||
* Parts of this code are (C) 2010, MyVoice CAD/CAM Services
|
||||
* All rights reserved.
|
||||
*
|
||||
* History
|
||||
* 2009.12.07 ver 1.00 Preliminary version, first Release
|
||||
* 2010.07.19 ver 1.10 Rob Jansen - MyVoice CAD/CAM Services:
|
||||
* Major cleaning and a rewrite of some functions
|
||||
* - adding ACK/NACK handling to the state machine
|
||||
* - adding a return result to the I2CEngine()
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "i2c.h"
|
||||
|
||||
volatile uint32_t I2CMasterState = I2CSTATE_IDLE;
|
||||
volatile uint32_t I2CSlaveState = I2CSTATE_IDLE;
|
||||
|
||||
volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
|
||||
volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
|
||||
volatile uint32_t I2CReadLength;
|
||||
volatile uint32_t I2CWriteLength;
|
||||
|
||||
volatile uint32_t RdIndex = 0;
|
||||
volatile uint32_t WrIndex = 0;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2C_IRQHandler
|
||||
**
|
||||
** Descriptions: I2C interrupt handler, deal with master mode only.
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: None
|
||||
**
|
||||
*****************************************************************************/
|
||||
void I2C_IRQHandler(void)
|
||||
{
|
||||
uint8_t StatValue;
|
||||
|
||||
/* this handler deals with master read and master write only */
|
||||
StatValue = I2C_I2CSTAT;
|
||||
switch ( StatValue )
|
||||
{
|
||||
case 0x08:
|
||||
/*
|
||||
* A START condition has been transmitted.
|
||||
* We now send the slave address and initialize
|
||||
* the write buffer
|
||||
* (we always start with a write after START+SLA)
|
||||
*/
|
||||
WrIndex = 0;
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
|
||||
I2CMasterState = I2CSTATE_PENDING;
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
/*
|
||||
* A repeated START condition has been transmitted.
|
||||
* Now a second, read, transaction follows so we
|
||||
* initialize the read buffer.
|
||||
*/
|
||||
RdIndex = 0;
|
||||
/* Send SLA with R bit set, */
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
|
||||
break;
|
||||
|
||||
case 0x18:
|
||||
/*
|
||||
* SLA+W has been transmitted; ACK has been received.
|
||||
* We now start writing bytes.
|
||||
*/
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
/*
|
||||
* SLA+W has been transmitted; NOT ACK has been received.
|
||||
* Send a stop condition to terminate the transaction
|
||||
* and signal I2CEngine the transaction is aborted.
|
||||
*/
|
||||
I2C_I2CCONSET = I2CONSET_STO;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
I2CMasterState = I2CSTATE_SLA_NACK;
|
||||
break;
|
||||
|
||||
case 0x28:
|
||||
/*
|
||||
* Data in I2DAT has been transmitted; ACK has been received.
|
||||
* Continue sending more bytes as long as there are bytes to send
|
||||
* and after this check if a read transaction should follow.
|
||||
*/
|
||||
if ( WrIndex < I2CWriteLength )
|
||||
{
|
||||
/* Keep writing as long as bytes avail */
|
||||
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( I2CReadLength != 0 )
|
||||
{
|
||||
/* Send a Repeated START to initialize a read transaction */
|
||||
/* (handled in state 0x10) */
|
||||
I2C_I2CCONSET = I2CONSET_STA; /* Set Repeated-start flag */
|
||||
}
|
||||
else
|
||||
{
|
||||
I2CMasterState = I2CSTATE_ACK;
|
||||
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||
}
|
||||
}
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
/*
|
||||
* Data byte in I2DAT has been transmitted; NOT ACK has been received
|
||||
* Send a STOP condition to terminate the transaction and inform the
|
||||
* I2CEngine that the transaction failed.
|
||||
*/
|
||||
I2C_I2CCONSET = I2CONSET_STO;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
I2CMasterState = I2CSTATE_NACK;
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
/*
|
||||
* Arbitration loss in SLA+R/W or Data bytes.
|
||||
* This is a fatal condition, the transaction did not complete due
|
||||
* to external reasons (e.g. hardware system failure).
|
||||
* Inform the I2CEngine of this and cancel the transaction
|
||||
* (this is automatically done by the I2C hardware)
|
||||
*/
|
||||
I2CMasterState = I2CSTATE_ARB_LOSS;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
/*
|
||||
* SLA+R has been transmitted; ACK has been received.
|
||||
* Initialize a read.
|
||||
* Since a NOT ACK is sent after reading the last byte,
|
||||
* we need to prepare a NOT ACK in case we only read 1 byte.
|
||||
*/
|
||||
if ( I2CReadLength == 1 )
|
||||
{
|
||||
/* last (and only) byte: send a NACK after data is received */
|
||||
I2C_I2CCONCLR = I2CONCLR_AAC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* more bytes to follow: send an ACK after data is received */
|
||||
I2C_I2CCONSET = I2CONSET_AA;
|
||||
}
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x48:
|
||||
/*
|
||||
* SLA+R has been transmitted; NOT ACK has been received.
|
||||
* Send a stop condition to terminate the transaction
|
||||
* and signal I2CEngine the transaction is aborted.
|
||||
*/
|
||||
I2C_I2CCONSET = I2CONSET_STO;
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
I2CMasterState = I2CSTATE_SLA_NACK;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
/*
|
||||
* Data byte has been received; ACK has been returned.
|
||||
* Read the byte and check for more bytes to read.
|
||||
* Send a NOT ACK after the last byte is received
|
||||
*/
|
||||
I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
|
||||
if ( RdIndex < (I2CReadLength-1) )
|
||||
{
|
||||
/* lmore bytes to follow: send an ACK after data is received */
|
||||
I2C_I2CCONSET = I2CONSET_AA;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* last byte: send a NACK after data is received */
|
||||
I2C_I2CCONCLR = I2CONCLR_AAC;
|
||||
}
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
|
||||
case 0x58:
|
||||
/*
|
||||
* Data byte has been received; NOT ACK has been returned.
|
||||
* This is the last byte to read.
|
||||
* Generate a STOP condition and flag the I2CEngine that the
|
||||
* transaction is finished.
|
||||
*/
|
||||
I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
|
||||
I2CMasterState = I2CSTATE_ACK;
|
||||
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CStart
|
||||
**
|
||||
** Descriptions: Create I2C start condition, a timeout
|
||||
** value is set if the I2C never gets started,
|
||||
** and timed out. It's a fatal error.
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: true or false, return false if timed out
|
||||
**
|
||||
*****************************************************************************/
|
||||
static uint32_t I2CStart( void )
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
|
||||
/*--- Issue a start condition ---*/
|
||||
I2C_I2CCONSET = I2CONSET_STA; /* Set Start flag */
|
||||
|
||||
while((I2CMasterState != I2CSTATE_PENDING) && (timeout < MAX_TIMEOUT))
|
||||
{
|
||||
timeout++;
|
||||
}
|
||||
|
||||
return (timeout < MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CStop
|
||||
**
|
||||
** Descriptions: Set the I2C stop condition
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: true or never return
|
||||
**
|
||||
*****************************************************************************/
|
||||
static uint32_t I2CStop( void )
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
|
||||
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||
I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
|
||||
|
||||
/*--- Wait for STOP detected ---*/
|
||||
while((I2C_I2CCONSET & I2CONSET_STO) && (timeout < MAX_TIMEOUT))
|
||||
{
|
||||
timeout++;
|
||||
}
|
||||
return (timeout >= MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CInit
|
||||
**
|
||||
** Descriptions: Initialize I2C controller
|
||||
**
|
||||
** parameters: I2c mode is either MASTER or SLAVE
|
||||
** Returned value: true or false, return false if the I2C
|
||||
** interrupt handler was not installed correctly
|
||||
**
|
||||
*****************************************************************************/
|
||||
uint32_t i2cInit( uint32_t I2cMode )
|
||||
{
|
||||
SCB_PRESETCTRL |= (0x1<<1);
|
||||
|
||||
// Enable I2C clock
|
||||
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_I2C);
|
||||
|
||||
// Configure pin 0.4 for SCL
|
||||
IOCON_PIO0_4 &= ~(IOCON_PIO0_4_FUNC_MASK | IOCON_PIO0_4_I2CMODE_MASK);
|
||||
IOCON_PIO0_4 |= (IOCON_PIO0_4_FUNC_I2CSCL);
|
||||
|
||||
// Configure pin 0.5 for SDA
|
||||
IOCON_PIO0_5 &= ~(IOCON_PIO0_5_FUNC_MASK | IOCON_PIO0_5_I2CMODE_MASK);
|
||||
IOCON_PIO0_5 |= IOCON_PIO0_5_FUNC_I2CSDA;
|
||||
|
||||
// Clear flags
|
||||
I2C_I2CCONCLR = I2C_I2CCONCLR_AAC |
|
||||
I2C_I2CCONCLR_SIC |
|
||||
I2C_I2CCONCLR_STAC |
|
||||
I2C_I2CCONCLR_I2ENC;
|
||||
|
||||
// See p.128 for appropriate values for SCLL and SCLH
|
||||
#if I2C_FAST_MODE_PLUS
|
||||
IOCON_PIO0_4 |= (IOCON_PIO0_4_I2CMODE_FASTPLUSI2C);
|
||||
IOCON_PIO0_5 |= (IOCON_PIO0_5_I2CMODE_FASTPLUSI2C);
|
||||
I2C_I2CSCLL = I2C_SCLL_HS_SCLL;
|
||||
I2C_I2CSCLH = I2C_SCLH_HS_SCLH;
|
||||
#else
|
||||
I2C_I2CSCLL = I2SCLL_SCLL;
|
||||
I2C_I2CSCLH = I2SCLH_SCLH;
|
||||
#endif
|
||||
|
||||
if ( I2cMode == I2CSLAVE )
|
||||
{
|
||||
I2C_I2CADR0 = SLAVE_ADDR;
|
||||
}
|
||||
|
||||
/* Enable the I2C Interrupt */
|
||||
NVIC_EnableIRQ(I2C_IRQn);
|
||||
I2C_I2CCONSET = I2C_I2CCONSET_I2EN;
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function name: I2CEngine
|
||||
**
|
||||
** Descriptions: The routine to complete a I2C transaction
|
||||
** from start to stop. All the intermitten
|
||||
** steps are handled in the interrupt handler.
|
||||
** Before this routine is called, the read
|
||||
** length, write length and I2C master buffer
|
||||
** need to be filled.
|
||||
**
|
||||
** parameters: None
|
||||
** Returned value: Any of the I2CSTATE_... values. See i2c.h
|
||||
**
|
||||
*****************************************************************************/
|
||||
uint32_t i2cEngine( void )
|
||||
{
|
||||
I2CMasterState = I2CSTATE_IDLE;
|
||||
RdIndex = 0;
|
||||
WrIndex = 0;
|
||||
if ( I2CStart() != TRUE )
|
||||
{
|
||||
I2CStop();
|
||||
return ( FALSE );
|
||||
}
|
||||
|
||||
/* wait until the state is a terminal state */
|
||||
while (I2CMasterState < 0x100);
|
||||
|
||||
return ( I2CMasterState );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
** End Of File
|
||||
******************************************************************************/
|
||||
|
||||
|
|
166
core/i2c/i2c.h
166
core/i2c/i2c.h
|
@ -1,83 +1,83 @@
|
|||
/*****************************************************************************
|
||||
* i2c.h: Header file for NXP LPC11xx Family Microprocessors
|
||||
*
|
||||
* Copyright(C) 2006, NXP Semiconductor
|
||||
* Parts of this code are (C) 2010, MyVoice CAD/CAM Services
|
||||
* All rights reserved.
|
||||
*
|
||||
* History
|
||||
* 2006.07.19 ver 1.00 Preliminary version, first Release
|
||||
* 2010.07.19 ver 1.10 Rob Jansen - MyVoice CAD/CAM Services
|
||||
* Updated to reflect new code
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __I2C_H
|
||||
#define __I2C_H
|
||||
|
||||
#include "projectconfig.h"
|
||||
|
||||
/*
|
||||
* These are states returned by the I2CEngine:
|
||||
*
|
||||
* IDLE - is never returned but only used internally
|
||||
* PENDING - is never returned but only used internally in the I2C functions
|
||||
* ACK - The transaction finished and the slave returned ACK (on all bytes)
|
||||
* NACK - The transaction is aborted since the slave returned a NACK
|
||||
* SLA_NACK - The transaction is aborted since the slave returned a NACK on the SLA
|
||||
* this can be intentional (e.g. an 24LC08 EEPROM states it is busy)
|
||||
* or the slave is not available/accessible at all.
|
||||
* ARB_LOSS - Arbitration loss during any part of the transaction.
|
||||
* This could only happen in a multi master system or could also
|
||||
* identify a hardware problem in the system.
|
||||
*/
|
||||
#define I2CSTATE_IDLE 0x000
|
||||
#define I2CSTATE_PENDING 0x001
|
||||
#define I2CSTATE_ACK 0x101
|
||||
#define I2CSTATE_NACK 0x102
|
||||
#define I2CSTATE_SLA_NACK 0x103
|
||||
#define I2CSTATE_ARB_LOSS 0x104
|
||||
|
||||
#define FAST_MODE_PLUS 0
|
||||
|
||||
#define I2C_BUFSIZE 6
|
||||
#define MAX_TIMEOUT 0x00FFFFFF
|
||||
|
||||
#define I2CMASTER 0x01
|
||||
#define I2CSLAVE 0x02
|
||||
|
||||
#define SLAVE_ADDR 0xA0
|
||||
#define READ_WRITE 0x01
|
||||
|
||||
#define RD_BIT 0x01
|
||||
|
||||
#define I2CONSET_I2EN 0x00000040 /* I2C Control Set Register */
|
||||
#define I2CONSET_AA 0x00000004
|
||||
#define I2CONSET_SI 0x00000008
|
||||
#define I2CONSET_STO 0x00000010
|
||||
#define I2CONSET_STA 0x00000020
|
||||
|
||||
#define I2CONCLR_AAC 0x00000004 /* I2C Control clear Register */
|
||||
#define I2CONCLR_SIC 0x00000008
|
||||
#define I2CONCLR_STAC 0x00000020
|
||||
#define I2CONCLR_I2ENC 0x00000040
|
||||
|
||||
#define I2DAT_I2C 0x00000000 /* I2C Data Reg */
|
||||
#define I2ADR_I2C 0x00000000 /* I2C Slave Address Reg */
|
||||
#define I2SCLH_SCLH 120 /* I2C SCL Duty Cycle High Reg */
|
||||
#define I2SCLL_SCLL 120 /* I2C SCL Duty Cycle Low Reg */
|
||||
#define I2SCLH_HS_SCLH 0x00000020 /* Fast Plus I2C SCL Duty Cycle High Reg */
|
||||
#define I2SCLL_HS_SCLL 0x00000020 /* Fast Plus I2C SCL Duty Cycle Low Reg */
|
||||
|
||||
|
||||
extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
|
||||
extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
|
||||
extern volatile uint32_t I2CReadLength, I2CWriteLength;
|
||||
|
||||
extern void I2C_IRQHandler( void );
|
||||
extern uint32_t i2cInit( uint32_t I2cMode );
|
||||
extern uint32_t i2cEngine( void );
|
||||
|
||||
#endif /* end __I2C_H */
|
||||
/****************************************************************************
|
||||
** End Of File
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* i2c.h: Header file for NXP LPC11xx Family Microprocessors
|
||||
*
|
||||
* Copyright(C) 2006, NXP Semiconductor
|
||||
* Parts of this code are (C) 2010, MyVoice CAD/CAM Services
|
||||
* All rights reserved.
|
||||
*
|
||||
* History
|
||||
* 2006.07.19 ver 1.00 Preliminary version, first Release
|
||||
* 2010.07.19 ver 1.10 Rob Jansen - MyVoice CAD/CAM Services
|
||||
* Updated to reflect new code
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __I2C_H
|
||||
#define __I2C_H
|
||||
|
||||
#include "projectconfig.h"
|
||||
|
||||
/*
|
||||
* These are states returned by the I2CEngine:
|
||||
*
|
||||
* IDLE - is never returned but only used internally
|
||||
* PENDING - is never returned but only used internally in the I2C functions
|
||||
* ACK - The transaction finished and the slave returned ACK (on all bytes)
|
||||
* NACK - The transaction is aborted since the slave returned a NACK
|
||||
* SLA_NACK - The transaction is aborted since the slave returned a NACK on the SLA
|
||||
* this can be intentional (e.g. an 24LC08 EEPROM states it is busy)
|
||||
* or the slave is not available/accessible at all.
|
||||
* ARB_LOSS - Arbitration loss during any part of the transaction.
|
||||
* This could only happen in a multi master system or could also
|
||||
* identify a hardware problem in the system.
|
||||
*/
|
||||
#define I2CSTATE_IDLE 0x000
|
||||
#define I2CSTATE_PENDING 0x001
|
||||
#define I2CSTATE_ACK 0x101
|
||||
#define I2CSTATE_NACK 0x102
|
||||
#define I2CSTATE_SLA_NACK 0x103
|
||||
#define I2CSTATE_ARB_LOSS 0x104
|
||||
|
||||
#define FAST_MODE_PLUS 0
|
||||
|
||||
#define I2C_BUFSIZE 6
|
||||
#define MAX_TIMEOUT 0x00FFFFFF
|
||||
|
||||
#define I2CMASTER 0x01
|
||||
#define I2CSLAVE 0x02
|
||||
|
||||
#define SLAVE_ADDR 0xA0
|
||||
#define READ_WRITE 0x01
|
||||
|
||||
#define RD_BIT 0x01
|
||||
|
||||
#define I2CONSET_I2EN 0x00000040 /* I2C Control Set Register */
|
||||
#define I2CONSET_AA 0x00000004
|
||||
#define I2CONSET_SI 0x00000008
|
||||
#define I2CONSET_STO 0x00000010
|
||||
#define I2CONSET_STA 0x00000020
|
||||
|
||||
#define I2CONCLR_AAC 0x00000004 /* I2C Control clear Register */
|
||||
#define I2CONCLR_SIC 0x00000008
|
||||
#define I2CONCLR_STAC 0x00000020
|
||||
#define I2CONCLR_I2ENC 0x00000040
|
||||
|
||||
#define I2DAT_I2C 0x00000000 /* I2C Data Reg */
|
||||
#define I2ADR_I2C 0x00000000 /* I2C Slave Address Reg */
|
||||
#define I2SCLH_SCLH 120 /* I2C SCL Duty Cycle High Reg */
|
||||
#define I2SCLL_SCLL 120 /* I2C SCL Duty Cycle Low Reg */
|
||||
#define I2SCLH_HS_SCLH 0x00000020 /* Fast Plus I2C SCL Duty Cycle High Reg */
|
||||
#define I2SCLL_HS_SCLL 0x00000020 /* Fast Plus I2C SCL Duty Cycle Low Reg */
|
||||
|
||||
|
||||
extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
|
||||
extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
|
||||
extern volatile uint32_t I2CReadLength, I2CWriteLength;
|
||||
|
||||
extern void I2C_IRQHandler( void );
|
||||
extern uint32_t i2cInit( uint32_t I2cMode );
|
||||
extern uint32_t i2cEngine( void );
|
||||
|
||||
#endif /* end __I2C_H */
|
||||
/****************************************************************************
|
||||
** End Of File
|
||||
*****************************************************************************/
|
||||
|
|
Loading…
Reference in New Issue