reform

MNT Reform: Open Source Portable Computer
Log (Feed) | Files | Refs (Tags) | README

i2c.c (13949B)


      1 /*****************************************************************************
      2  *   i2c.c:  I2C C file for NXP LPC11xx/13xx Family Microprocessors
      3  *
      4  *   Copyright(C) 2008, NXP Semiconductor
      5  *   Parts of this code are (C) 2010, MyVoice CAD/CAM Services
      6  *   All rights reserved.
      7  *
      8  *   History
      9  *   2009.12.07  ver 1.00    Preliminary version, first Release
     10  *   2010.07.19  ver 1.10    Rob Jansen - MyVoice CAD/CAM Services:
     11  *                           Major cleaning and a rewrite of some functions
     12  *                           - adding ACK/NACK handling to the state machine
     13  *                           - adding a return result to the I2CEngine()
     14  *
     15 *****************************************************************************/
     16 #include "projectconfig.h"
     17 
     18 #ifdef CFG_ENABLE_I2C
     19 
     20 #include "i2c.h"
     21 
     22 volatile uint32_t I2CMasterState = I2CSTATE_IDLE;
     23 volatile uint32_t I2CSlaveState = I2CSTATE_IDLE;
     24 
     25 volatile uint8_t i2c_write_buf[I2C_BUFSIZE];    // Master Mode
     26 volatile uint8_t i2c_read_buf[I2C_BUFSIZE];     // Master Mode
     27 
     28 volatile uint32_t i2c_read_len;
     29 volatile uint32_t i2c_write_len;
     30 
     31 volatile uint32_t I2CRdIndex;
     32 volatile uint32_t I2CWrIndex;
     33 
     34 volatile uint32_t _I2cMode;                       // I2CMASTER or I2CSLAVE (only master is used at present)
     35 
     36 /*****************************************************************************
     37 ** Function name:                I2C_IRQHandler
     38 **
     39 ** Descriptions:                I2C interrupt handler, deal with master mode only.
     40 **
     41 ** parameters:                        None
     42 ** Returned value:                None
     43 **
     44 *****************************************************************************/
     45 void I2C_IRQHandler(void)
     46 {
     47         uint8_t StatValue;
     48 
     49         /* this handler deals with master read and master write only */
     50         StatValue = LPC_I2C->STAT;
     51         switch ( StatValue )
     52         {
     53         case 0x08:
     54                 /*
     55                  * A START condition has been transmitted.
     56                  * We now send the slave address and initialize
     57                  * the write buffer
     58                  * (we always start with a write after START+SLA)
     59                  */
     60                 I2CWrIndex = 0;
     61                 LPC_I2C->DAT = i2c_write_buf[I2CWrIndex++];
     62                 LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
     63                 I2CMasterState = I2CSTATE_PENDING;
     64                 break;
     65 
     66         case 0x10:
     67                 /*
     68                  * A repeated START condition has been transmitted.
     69                  * Now a second, read, transaction follows so we
     70                  * initialize the read buffer.
     71                  */
     72                 I2CRdIndex = 0;
     73                 /* Send SLA with R bit set, */
     74                 LPC_I2C->DAT = i2c_write_buf[I2CWrIndex++];
     75                 LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
     76         break;
     77 
     78         case 0x18:
     79                 /*
     80                  * SLA+W has been transmitted; ACK has been received.
     81                  * We now start writing bytes.
     82                  */
     83                 LPC_I2C->DAT = i2c_write_buf[I2CWrIndex++];
     84                 LPC_I2C->CONCLR = I2CONCLR_SIC;
     85                 break;
     86 
     87         case 0x20:
     88                 /*
     89                  * SLA+W has been transmitted; NOT ACK has been received.
     90                  * Send a stop condition to terminate the transaction
     91                  * and signal I2CEngine the transaction is aborted.
     92                  */
     93                 LPC_I2C->CONSET = I2CONSET_STO;
     94                 LPC_I2C->CONCLR = I2CONCLR_SIC;
     95                 I2CMasterState = I2CSTATE_SLA_NACK;
     96                 break;
     97 
     98         case 0x28:
     99                 /*
    100                  * Data in I2DAT has been transmitted; ACK has been received.
    101                  * Continue sending more bytes as long as there are bytes to send
    102                  * and after this check if a read transaction should follow.
    103                  */
    104                 if ( I2CWrIndex < i2c_write_len )
    105                 {
    106                         /* Keep writing as long as bytes avail */
    107                         LPC_I2C->DAT = i2c_write_buf[I2CWrIndex++];
    108                 }
    109                 else
    110                 {
    111                         if ( i2c_read_len != 0 )
    112                         {
    113                                 /* Send a Repeated START to initialize a read transaction */
    114                                 /* (handled in state 0x10)                                */
    115                                 LPC_I2C->CONSET = I2CONSET_STA;        /* Set Repeated-start flag */
    116                         }
    117                         else
    118                         {
    119                                 I2CMasterState = I2CSTATE_ACK;
    120                                 LPC_I2C->CONSET = I2CONSET_STO;      /* Set Stop flag */
    121                         }
    122                 }
    123                 LPC_I2C->CONCLR = I2CONCLR_SIC;
    124                 break;
    125 
    126         case 0x30:
    127                 /*
    128                  * Data byte in I2DAT has been transmitted; NOT ACK has been received
    129                  * Send a STOP condition to terminate the transaction and inform the
    130                  * I2CEngine that the transaction failed.
    131                  */
    132                 LPC_I2C->CONSET = I2CONSET_STO;
    133                 LPC_I2C->CONCLR = I2CONCLR_SIC;
    134                 I2CMasterState = I2CSTATE_NACK;
    135                 break;
    136 
    137         case 0x38:
    138                 /*
    139                  * Arbitration loss in SLA+R/W or Data bytes.
    140                  * This is a fatal condition, the transaction did not complete due
    141                  * to external reasons (e.g. hardware system failure).
    142                  * Inform the I2CEngine of this and cancel the transaction
    143                  * (this is automatically done by the I2C hardware)
    144                  */
    145                 I2CMasterState = I2CSTATE_ARB_LOSS;
    146                 LPC_I2C->CONCLR = I2CONCLR_SIC;
    147                 break;
    148 
    149         case 0x40:
    150                 /*
    151                  * SLA+R has been transmitted; ACK has been received.
    152                  * Initialize a read.
    153                  * Since a NOT ACK is sent after reading the last byte,
    154                  * we need to prepare a NOT ACK in case we only read 1 byte.
    155                  */
    156                 if ( i2c_read_len == 1 )
    157                 {
    158                         /* last (and only) byte: send a NACK after data is received */
    159                         LPC_I2C->CONCLR = I2CONCLR_AAC;
    160                 }
    161                 else
    162                 {
    163                         /* more bytes to follow: send an ACK after data is received */
    164                         LPC_I2C->CONSET = I2CONSET_AA;
    165                 }
    166                 LPC_I2C->CONCLR = I2CONCLR_SIC;
    167                 break;
    168 
    169         case 0x48:
    170                 /*
    171                  * SLA+R has been transmitted; NOT ACK has been received.
    172                  * Send a stop condition to terminate the transaction
    173                  * and signal I2CEngine the transaction is aborted.
    174                  */
    175                 LPC_I2C->CONSET = I2CONSET_STO;
    176                 LPC_I2C->CONCLR = I2CONCLR_SIC;
    177                 I2CMasterState = I2CSTATE_SLA_NACK;
    178                 break;
    179 
    180         case 0x50:
    181                 /*
    182                  * Data byte has been received; ACK has been returned.
    183                  * Read the byte and check for more bytes to read.
    184                  * Send a NOT ACK after the last byte is received
    185                  */
    186                 i2c_read_buf[I2CRdIndex++] = LPC_I2C->DAT;
    187                 if ( I2CRdIndex < (i2c_read_len-1) )
    188                 {
    189                         /* lmore bytes to follow: send an ACK after data is received */
    190                         LPC_I2C->CONSET = I2CONSET_AA;
    191                 }
    192                 else
    193                 {
    194                         /* last byte: send a NACK after data is received */
    195                         LPC_I2C->CONCLR = I2CONCLR_AAC;
    196                 }
    197                 LPC_I2C->CONCLR = I2CONCLR_SIC;
    198                 break;
    199 
    200         case 0x58:
    201                 /*
    202                  * Data byte has been received; NOT ACK has been returned.
    203                  * This is the last byte to read.
    204                  * Generate a STOP condition and flag the I2CEngine that the
    205                  * transaction is finished.
    206                  */
    207                 i2c_read_buf[I2CRdIndex++] = LPC_I2C->DAT;
    208                 I2CMasterState = I2CSTATE_ACK;
    209                 LPC_I2C->CONSET = I2CONSET_STO;        /* Set Stop flag */
    210                 LPC_I2C->CONCLR = I2CONCLR_SIC;        /* Clear SI flag */
    211                 break;
    212 
    213         default:
    214                 LPC_I2C->CONCLR = I2CONCLR_SIC;
    215                 break;
    216   }
    217   return;
    218 }
    219 
    220 /*****************************************************************************
    221 ** Function name:        I2CStart
    222 **
    223 ** Descriptions:        Create I2C start condition, a timeout
    224 **                        value is set if the I2C never gets started,
    225 **                        and timed out. It's a fatal error.
    226 **
    227 ** parameters:                None
    228 ** Returned value:        true or false, return false if timed out
    229 **
    230 *****************************************************************************/
    231 static uint32_t I2CStart( void )
    232 {
    233   uint32_t timeout = 0;
    234 
    235   /*--- Issue a start condition ---*/
    236   LPC_I2C->CONSET = I2CONSET_STA;      /* Set Start flag */
    237 
    238   while((I2CMasterState != I2CSTATE_PENDING) && (timeout < MAX_TIMEOUT))
    239   {
    240     timeout++;
    241   }
    242 
    243   return (timeout < MAX_TIMEOUT);
    244 }
    245 
    246 /*****************************************************************************
    247 ** Function name:        I2CStop
    248 **
    249 ** Descriptions:        Set the I2C stop condition
    250 **
    251 ** parameters:                None
    252 ** Returned value:        true or never return
    253 **
    254 *****************************************************************************/
    255 static uint32_t I2CStop( void )
    256 {
    257   uint32_t timeout = 0;
    258 
    259   LPC_I2C->CONSET = I2CONSET_STO;  /* Set Stop flag */
    260   LPC_I2C->CONCLR = I2CONCLR_SIC;  /* Clear SI flag */
    261 
    262   /*--- Wait for STOP detected ---*/
    263   while((LPC_I2C->CONSET & I2CONSET_STO) && (timeout < MAX_TIMEOUT))
    264   {
    265     timeout++;
    266   }
    267   return (timeout >= MAX_TIMEOUT);
    268 }
    269 
    270 /*****************************************************************************
    271 ** Function name:        I2CInit
    272 **
    273 ** Descriptions:        Initialize I2C controller
    274 **
    275 ** parameters:                I2c mode is either MASTER or SLAVE
    276 ** Returned value:        true or false, return false if the I2C
    277 **                        interrupt handler was not installed correctly
    278 **
    279 *****************************************************************************/
    280 uint32_t i2cInit( uint32_t I2cMode )
    281 {
    282   _I2cMode = I2cMode;
    283 
    284   LPC_SYSCON->PRESETCTRL |= (0x1<<1);
    285 
    286   /* Enable AHB clock to the I2C domain. */
    287   LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 5);
    288 
    289   /* Set P0.4 to SCL and I2C mode (open drain) */
    290   LPC_IOCON->PIO0_4 &= ~0x07 | 0x300; /* Add I2C mode mask */
    291   LPC_IOCON->PIO0_4 |= 0x01;
    292 
    293   /* Set P0.5 to SDA and I2C mode (open drain) */
    294   LPC_IOCON->PIO0_5 &= ~0x07 | 0x300; /* Add I2C mode mask */
    295   LPC_IOCON->PIO0_5 |= 0x01;
    296 
    297   // Clear flags
    298   LPC_I2C->CONCLR = I2CONCLR_AAC |
    299                   I2CONCLR_SIC |
    300                   I2CONCLR_STAC |
    301                   I2CONCLR_I2ENC;
    302 
    303 #if I2C_FAST_MODE_PLUS
    304   LPC_IOCON->PIO0_4 |= (0x200); /* Fast mode plus */
    305   LPC_IOCON->PIO0_5 |= (0x200); /* Fast mode plus */
    306   LPC_I2C->SCLL   = I2C_SCLL_HS_SCLL;
    307   LPC_I2C->SCLH   = I2C_SCLH_HS_SCLH;
    308 #else
    309   LPC_I2C->SCLL   = I2SCLL_SCLL;
    310   LPC_I2C->SCLH   = I2SCLH_SCLH;
    311 #endif
    312 
    313   if ( _I2cMode == I2CSLAVE )
    314   {
    315     LPC_I2C->ADR0 = SLAVE_ADDR;
    316     I2CSlaveState = I2C_IDLE;
    317   }
    318 
    319   /* Enable the I2C Interrupt */
    320   NVIC_EnableIRQ(I2C_IRQn);
    321   if ( _I2cMode == I2CMASTER )
    322   {
    323     LPC_I2C->CONSET = I2CONSET_I2EN;
    324   }
    325 
    326   return( TRUE );
    327 }
    328 
    329 /*****************************************************************************
    330 ** Function name:        I2CEngine
    331 **
    332 ** Descriptions:        The routine to complete a I2C transaction
    333 **                        from start to stop. All the intermitten
    334 **                        steps are handled in the interrupt handler.
    335 **                        Before this routine is called, the read
    336 **                        length, write length and I2C master buffer
    337 **                        need to be filled.
    338 **
    339 ** parameters:                None
    340 ** Returned value:        Any of the I2CSTATE_... values. See i2c.h
    341 **
    342 *****************************************************************************/
    343 uint32_t i2cEngine( void )
    344 {
    345   I2CMasterState = I2CSTATE_IDLE;
    346   I2CRdIndex = 0;
    347   I2CWrIndex = 0;
    348   if ( I2CStart() != TRUE )
    349   {
    350         // I2C timed out
    351     I2CStop();
    352     return ( I2CSTATE_TIMEOUT );
    353   }
    354 
    355   /* wait until the state is a terminal state */
    356   while (I2CMasterState < 0x100);
    357 
    358   return ( I2CMasterState );
    359 }
    360 
    361 /*****************************************************************************
    362 ** Function name:        i2cCheckAddress
    363 **
    364 ** Descriptions:        The routine checks if a device is present at
    365 **                        the specified address.
    366 **
    367 ** parameters:                8-bit address byte including the read bit
    368 ** Returned value:        True if a device ACKed, otherwise False
    369 **
    370 *****************************************************************************/
    371 bool i2cCheckAddress( uint8_t addr )
    372 {
    373   uint32_t i2cState;
    374 
    375   // Send the addr byte and check for ACK
    376   i2c_write_len = 1;
    377   i2c_read_len = 0;
    378   i2c_write_buf[0] = addr;
    379   i2cState = i2cEngine();
    380 
    381   // Check if we got an ACK
    382   if ((i2cState == I2CSTATE_NACK) || (i2cState == I2CSTATE_SLA_NACK))
    383   {
    384     // I2C slave didn't acknowledge the master transfer
    385     // The device probably isn't connected
    386     return false;
    387   }
    388   else if (i2cState == I2CSTATE_TIMEOUT)
    389   {
    390     // I2C timed out waiting for start/stop
    391         return false;
    392   }
    393   else
    394   {
    395     // I2C device found
    396     return true;
    397   }
    398 }
    399 
    400 /******************************************************************************
    401 **                            End Of File
    402 ******************************************************************************/
    403 
    404 #endif