##############################################################################
#                                                                            #
# IAR ARM ANSI C/C++ Compiler V4.11A/W32               20/Jul/2004  18:58:52 #
# Copyright 1999-2004 IAR Systems. All rights reserved.                      #
#                                                                            #
#    Cpu mode        =  arm                                                  #
#    Endian          =  little                                               #
#    Stack alignment =  4                                                    #
#    Source file     =  C:\medusa\i2cmaster.c                                #
#    Command line    =  -I "C:\Program Files\IAR Systems\Embedded Workbench  #
#                       4.0\ARM\INC\" -lc C:\medusa\Debug\List\ -la          #
#                       C:\medusa\Debug\List\ -o C:\medusa\Debug\Obj\ -s2    #
#                       --no_cse --no_unroll --no_inline --no_code_motion    #
#                       --no_tbaa --no_clustering --no_scheduling --debug    #
#                       --cpu_mode arm --endian little --cpu ARM7TDMI-S      #
#                       --stack_align 4 -e --fpu None                        #
#                       "-D_DLIB_CONFIG_FILE=C:\Program Files\IAR            #
#                       Systems\Embedded Workbench                           #
#                       4.0\ARM\LIB\dl4tpannl8n.h" C:\medusa\i2cmaster.c     #
#    List file       =  C:\medusa\Debug\List\i2cmaster.lst                   #
#    Object file     =  C:\medusa\Debug\Obj\i2cmaster.r79                    #
#                                                                            #
#                                                                            #
##############################################################################

C:\medusa\i2cmaster.c
      1          #include "archinc.h"
      2          #include "i2cregs.h"
      3          #include "i2cmaster.h"
      4          
      5          #ifdef CONFIG_INCLUDE_LPC210X_I2C
      6          
      7          #define GET_STATUS(a)       ((a) = (I2STAT & 0xff))
      8          #define SLAVE_ADDR_WRITE(a) ((a) & 0xfe)
      9          #define SLAVE_ADDR_READ(a)  ((a) | 0x01)
     10          
     11          #define RECEIVE_I2C_DATA(i)  (readData[(i)] |= (((unsigned short)I2DAT) & 0xff)
     12          #define SEND_I2C_DATA(i)     (I2DAT = ((lpc210x_reg)(writeData[(i)] & 0xff)))
     13          
     14          #define GET_I2C_ADDR_WRITE(i)  ((writeData[(i)] >> 8) & 0xff)
     15          #define GET_I2C_ADDR_READ(i)  ((readData[(i)] >> 8) & 0xff)
     16          #define GET_I2C_DATA_READ(i)   (readData[(i)] & 0xff)
     17          
     18          #define PUT_DATA_WRITE(i, a, d) (writeData[(i)] = ((((a) & 0xff) << 8) | ((d) & 0xff)))
     19          
     20          typedef enum {none, addr, data, arbLost} i2cError;
     21          typedef enum {idle, ready, busy, error} i2cState;
     22          typedef enum {noop, probe, read, write} i2cOp;
     23          
     24          static i2cState currentState = idle;
     25          static i2cOp currentOp = noop;
     26          static i2cError currentError = none;
                                 ^
Warning[Pe550]: variable "currentError" was set but never used
     27          
     28          static boolean sendStop;
     29          
     30          static unsigned short readData[CONFIG_I2C_RX_BUFFER_SIZE];
     31          static int readHead = 0;
     32          static int readTail = 0;
     33          static int readLen  = 0;
     34          static int readRequestLen;
     35          
     36          static unsigned short writeData[CONFIG_I2C_TX_BUFFER_SIZE];
     37          static int writeHead = 0;
     38          static int writeTail = 0;
     39          static int writeLen  = 0;
     40          
     41          static unsigned char mySlaveAddr;
                                      ^
Warning[Pe550]: variable "mySlaveAddr" was set but never used
     42          static unsigned char slaveAddr;
     43          
     44          static unsigned int isrEntry = 0;
     45          static unsigned int maxTxLen = 0;
     46          
     47          /* ISR declaration */
     48          DECLARE_ISR(i2cmasterSiIsr);
     49          
     50          #ifdef CONFIG_TOOLCHAIN_IAR
     51          #pragma inline
     52          #endif
     53          static INLINE_KEYWORD void setState(i2cState newState)
     54          {
     55            currentState = newState;
     56          }
     57          
     58          #ifdef CONFIG_TOOLCHAIN_IAR
     59          #pragma inline
     60          #endif
     61          static INLINE_KEYWORD int sendStartCondition(void)
     62          {
     63            int retVal = -1;
     64          
     65            if ((currentState == idle) || (currentState == ready)) { 
     66              I2CONSET = CTRL_SET_START;
     67              setState(busy);
     68              retVal = 0;
     69              }
     70          
     71            return retVal;
     72          }
     73          
     74          #ifdef CONFIG_TOOLCHAIN_IAR
     75          #pragma inline
     76          #endif
     77          static INLINE_KEYWORD void sendStopCondition(void)
     78          {
     79            I2CONSET = CTRL_SET_STOP;
     80            setState(idle);
     81          }
     82          
     83          #ifdef CONFIG_TOOLCHAIN_IAR
     84          #pragma inline
     85          #endif
     86          static INLINE_KEYWORD void waitUntilComplete(void)
     87          {
     88            while (currentState == busy)
     89              ;
     90          }
     91          
     92          #ifdef CONFIG_TOOLCHAIN_IAR
     93          #pragma inline
     94          #endif
     95          static INLINE_KEYWORD void reInitState(void)
     96          {
     97            setState(idle);
     98            currentOp = noop;
     99            currentError = none;
    100          }
    101          
    102          
    103          static unsigned short tmp;
    104          static lpc210x_reg regData;
    105          
    106          #ifdef CONFIG_TOOLCHAIN_IAR
    107          #pragma inline
    108          #endif
    109          static INLINE_KEYWORD void updateMasterReadState(unsigned int newStatus)
    110          {
    111            switch(newStatus) {
    112              case 0x00:
    113                break;
    114              case 0x08:
    115              case 0x10:
    116                // StartSent: clear start bit and write addr+r to I2DATA
    117                // RepeatedStartSent: clear start bit and write addr+r to I2DATA
    118                I2CONCLR = CTRL_CLR_START;
    119                I2DAT = ((lpc210x_reg)slaveAddr);
    120                break;
    121              case 0x38:
    122                // LostArbitration: return interface to idle state for next xaction
    123                setState(error);
    124                currentError = arbLost;
    125                break;
    126              case 0x40:
    127                // AddrSentAck: receive the first data byte
    128                  if (readRequestLen == 1) {
    129                    I2CONCLR = CTRL_CLR_AA;
    130                    }
    131                  else {
    132                    I2CONSET = CTRL_SET_AA;
    133                    }
    134                break;
    135              case 0x50:
    136                // DataReceivedAck: read another data byte
    137                if ((readRequestLen > 0) && (readLen != CONFIG_I2C_RX_BUFFER_SIZE)) {
    138                  tmp = (unsigned short)((slaveAddr << 8) & 0xff);
    139                  regData = I2DAT;
    140                  tmp |= (regData & 0xff);
    141                  readData[readHead] = tmp;
    142                  circInc(readHead, 0, (CONFIG_I2C_RX_BUFFER_SIZE-1));
    143                  readLen++;
    144                  readRequestLen--;
    145                  if (readRequestLen == 1) {
    146                    I2CONCLR = CTRL_CLR_AA;
    147                    }
    148                  }
    149                break;
    150              case 0x48:
    151                // AddrSentNak: nobody home -- send stop condition and bail 
    152                I2CONSET = CTRL_SET_STOP;
    153                setState(error);
    154                currentError = addr;
    155                // TODO: reset queue??
    156                break;
    157              case 0x58:
    158                // DataReceivedNak: we should assert a NAK on the last data byte
    159                // read. Handle this as it is a normal condition if we are finished
    160                // reading, else indicate an error
    161                if ((readRequestLen == 1) && (readLen != CONFIG_I2C_RX_BUFFER_SIZE)) {
    162                  tmp = (unsigned short)((slaveAddr << 8) & 0xff);
    163                  regData = I2DAT;
    164                  tmp |= (regData & 0xff);
    165                  readData[readHead] = tmp;
    166                  circInc(readHead, 0, (CONFIG_I2C_RX_BUFFER_SIZE-1));
    167                  readLen++;
    168                  readRequestLen--;
    169                  if (sendStop == true) {
    170                    I2CONSET = CTRL_SET_STOP;
    171                    setState(idle);
    172                    }
    173                  else {
    174                    setState(ready);
    175                    }
    176                  }
    177                else {
    178                  I2CONSET = CTRL_SET_STOP;
    179                  setState(error);
    180                  currentError = data;
    181                  }
    182                // TODO: reset queue??
    183                break;
    184              case 0xF8:
    185                // Noop: set interface to idle
    186                break;
    187              default:
    188                break;
    189              }
    190          }
    191          
    192          #ifdef CONFIG_TOOLCHAIN_IAR
    193          #pragma inline
    194          #endif
    195          static INLINE_KEYWORD void updateMasterWriteState(unsigned int newStatus)
    196          {
    197            switch(newStatus) {
    198              case 0x08:
    199              case 0x10:
    200                // StartSent: clear start bit and write addr+w to I2DATA
    201                // RepeatedStartSent: clear start bit and write addr+w to I2DATA
    202                I2CONCLR = CTRL_CLR_START;
    203          
    204          #if 0
    205                if (currentOp == write) {
    206                  slaveAddr = GET_I2C_ADDR_WRITE(writeHead);
    207                  }
    208          #endif
    209          
    210                I2DAT = ((lpc210x_reg)slaveAddr);
    211                break;
    212              case 0x18:
    213              case 0x28:
    214                // AddrSentAck: write the first data byte
    215                // DataSentAck: 
    216                if (currentOp == probe) {
    217                  I2CONSET = CTRL_SET_STOP;
    218                  setState(idle);
    219                  }
    220                else if ((currentOp == write) && (writeLen > 0)) {
    221                  IOSET = ((lpc210x_reg)0x00000200);
    222                  SEND_I2C_DATA(writeTail);
    223                  circInc(writeTail, 0, (CONFIG_I2C_TX_BUFFER_SIZE-1));
    224                  writeLen--;
    225                  IOCLR = ((lpc210x_reg)0x00000200);
    226                  }
    227                else {
    228                  // nothing to do: send a stop condition and idle the interface
    229                  if (sendStop == true) {
    230                    I2CONSET = CTRL_SET_STOP;
    231                    setState(idle);
    232                    }
    233                  else {
    234                    setState(ready);
    235                    }
    236                  }
    237                break;
    238              case 0x20:
    239                // AddrSentNak: send stop condition and bail on the xaction
    240                I2CONSET = CTRL_SET_STOP;
    241                setState(error);
    242                currentError = addr;
    243                break;
    244              case 0x30:
    245                // DataSentNak: send stop condition and bail on the xaction
    246                // TODO: implement retry based on last stored byte value
    247                I2CONSET = CTRL_SET_STOP;
    248                setState(error);
    249                currentError = data;
    250                break;
    251              case 0x38:
    252                // LostArbitration: return interface to idle state for next xaction
    253                setState(error);
    254                currentError = arbLost;
    255                break;
    256              case 0xF8:
    257                // Noop: set interface to idle
    258                break;
    259              default:
    260                break;
    261              }
    262          }
    263          
    264          /*
    265           * SI ISR
    266           */
    267          
    268          static unsigned int pollStatus;
    269          
    270          ISR_FUNCTION(i2cmasterSiIsr)
    271          {
    272            ISR_ENTER()
    273          
    274            isrEntry++;
    275          
    276            GET_STATUS(pollStatus);
    277          
    278            switch(currentOp) {
    279              case probe:
    280              case write:
    281                updateMasterWriteState(pollStatus);
    282                break;
    283              case read:
    284                updateMasterReadState(pollStatus);
    285                break;
    286              default:
    287                // TODO: error handling
    288                break;
    289              }
    290          
    291            // acknowledge the interrupt by clearing the SI bit
    292            I2CONCLR = CTRL_CLR_IRQ;
    293            
    294            // acknowledge the interrupt at the VIC
    295            VICIrqDone;
    296          
    297            ISR_LEAVE()
    298          }
    299          
    300          int i2cmasterInit(unsigned char myAddress) 
    301          {
    302            int retStat;
    303          
    304            mySlaveAddr = myAddress;
    305          
    306            // initialize state
    307            reInitState();
    308          
    309            // TODO: adjust this based on PLL/peripheral clock
    310            I2SCLL = (lpc210x_reg)0x8000;
    311            I2SCLH = (lpc210x_reg)0x8000;
    312          
    313            // enable the I2C interface
    314            I2CONSET = CTRL_SET_ENABLE;
    315          
    316            // send stop condition to reset the bus to an idle state
    317            sendStopCondition();
    318          
    319            // connect the interrupt vector
    320            if ((retStat = armvicIntConnect(LPC210X_IRQVEC_I2C, i2cmasterSiIsr)) != 0)
    321              return retStat;
    322          
    323            // enable the interrupt
    324            if ((retStat = armvicIntEnable(LPC210X_IRQVEC_I2C)) != 0)
    325              return retStat;
    326          
    327            return 0;
    328          }
    329          
    330          int i2cmasterPut(unsigned char putAddr, unsigned char putData)
    331          {
    332            int retStat = -1;
    333          
    334            if (writeLen != CONFIG_I2C_TX_BUFFER_SIZE) {
    335              IRQ_DISABLE();
    336              PUT_DATA_WRITE(writeHead, putAddr, putData);
    337              writeLen++;
    338              circInc(writeHead, 0, (CONFIG_I2C_TX_BUFFER_SIZE-1));
    339              IRQ_ENABLE();
    340              maxTxLen = ((writeLen > maxTxLen) ? writeLen : maxTxLen);
    341              retStat = 0;
    342              }
    343          
    344            return retStat;
    345          }
    346          
    347          int i2cmasterGetData(unsigned char *pGetData)
    348          {
    349            unsigned char tossAddr;
    350            return i2cmasterGet(&tossAddr, pGetData);
    351          }
    352          
    353          
    354          // gets transactions that have been completed, possibly filter by address
    355          int i2cmasterGet(unsigned char *pGetAddr, unsigned char *pGetData)
    356          {
    357            int retStat = -1;
    358            unsigned short tmpData;
    359          
    360            if (readLen == 0)
    361              return retStat;
    362            
    363            if ((pGetData == NULL) || (pGetAddr == NULL) || (currentState != idle))
    364              return retStat;
    365          
    366            tmpData = readData[readTail];
    367          
    368            IRQ_DISABLE();
    369            circInc(readTail, 0, (CONFIG_I2C_RX_BUFFER_SIZE-1));
    370            readLen--;
    371            IRQ_ENABLE();
    372          
    373            *pGetAddr = GET_I2C_ADDR_READ(tmpData);
    374            *pGetData = (unsigned char)(tmpData & 0xff);
    375            
    376            retStat = 0;
    377          
    378            return retStat;
    379          }
    380          
    381          int i2cmasterProbe(unsigned char probeAddr)
    382          {
    383            int retVal = -1;
    384          
    385            if ((currentState == busy) || (currentState == error))
    386              return retVal;
    387          
    388            currentOp = probe;
    389            slaveAddr = SLAVE_ADDR_WRITE(probeAddr);
    390          
    391            if (sendStartCondition() == 0) {
    392              waitUntilComplete();
    393              retVal = ((currentState == error) ? -1 : 0);
    394              }
    395          
    396            // reset the interface, no stop condition required
    397            reInitState();
    398          
    399            return retVal;
    400          }
    401          
    402          int i2cmasterReceive(unsigned char recvAddr, int maxRecvBytes, boolean recvSendStop)
    403          {
    404            int retVal = -1;
    405          
    406            if ((currentState == busy) || (currentState == error))
    407              return retVal;
    408          
    409            currentOp = read;
    410            slaveAddr = SLAVE_ADDR_READ(recvAddr);
    411            sendStop = recvSendStop;
    412            readRequestLen = maxRecvBytes;
    413          
    414            sendStartCondition();
    415          
    416            waitUntilComplete();
    417          
    418            retVal = ((currentState == error) ? -1 : 0);
    419          
    420            reInitState();
    421          
    422            return retVal;
    423          }
    424          
    425          int i2cmasterSend(unsigned char sendAddr, boolean sendSendStop)
    426          {
    427            int retVal = -1;
    428          
    429            if ((currentState == busy) || (currentState == error))
    430              return retVal;
    431          
    432            currentOp = write;
    433            slaveAddr = SLAVE_ADDR_WRITE(sendAddr);
    434            sendStop = sendSendStop;
    435          
    436            sendStartCondition();
    437          
    438            waitUntilComplete();
    439          
    440            retVal = ((currentState == error) ? -1 : 0);
    441            reInitState();
    442          
    443            return retVal;
    444          }
    445          
    446          int i2cmasterSendOne(unsigned char sendAddr, unsigned char sendData, boolean sendSendStop)
    447          {
    448            int retVal = -1;
    449          
    450            if (i2cmasterPut(sendAddr, sendData) != -1) {
    451              retVal = i2cmasterSend(sendAddr, sendSendStop);
    452              }
    453          
    454            return retVal;
    455          }
    456          
    457          int i2cmasterSendMult(unsigned char sendAddr, unsigned char * pSendData, int numBytes, boolean sendSendStop)
    458          {
    459            int i = 0;
    460            int retVal = 0;
    461          
    462            while ((i < numBytes) && (retVal != -1)) {
    463              retVal = i2cmasterPut(sendAddr, *(pSendData + i));
    464              i++;
    465              }
    466          
    467            if (retVal != -1) {
    468              retVal = i2cmasterSend(sendAddr, sendSendStop);
    469              }
    470          
    471            return retVal;
    472          }
    473          
    474          #endif /* CONFIG_INCLUDE_LPC210X_I2C */

   Maximum stack usage in bytes:

     Function               CSTACK CSTACK IRQSTACK
     --------               ------ ------ --------
     i2cmasterGet               8      0        0
     i2cmasterGetData          12      0        0
     i2cmasterInit             12      0        0
     i2cmasterProbe            12      0        0
     i2cmasterPut               4      0        0
     i2cmasterReceive          20      0        0
     i2cmasterSend             16      0        0
     i2cmasterSendMult         28      0        0
     i2cmasterSendOne          20      0        0
     i2cmasterSiIsr             0     20        0
     reInitState                4      0        0
     sendStartCondition         8      0        0
     sendStopCondition          4      0        0
     setState                   0      0        0
     updateMasterReadState      8      0        0
     updateMasterWriteState     8      0        0
     waitUntilComplete          0      0        0


   Segment part sizes:

     Function/Label         Bytes
     --------------         -----
     currentState              1
     currentOp                 1
     currentError              1
     sendStop                  4
     readData                 64
     readHead                  4
     readTail                  4
     readLen                   4
     readRequestLen            4
     writeData                64
     writeHead                 4
     writeTail                 4
     writeLen                  4
     mySlaveAddr               1
     slaveAddr                 1
     isrEntry                  4
     maxTxLen                  4
     setState                 12
     sendStartCondition       84
     sendStopCondition        32
     ??waitUntilComplete_0    20
     reInitState              40
     tmp                       2
     regData                   4
     updateMasterReadState   872
     updateMasterWriteState  532
     pollStatus                4
     i2cmasterSiIsr          208
     i2cmasterInit           148
     i2cmasterPut            244
     i2cmasterGetData         32
     i2cmasterGet            252
     i2cmasterProbe          144
     i2cmasterReceive        160
     i2cmasterSend           148
     i2cmasterSendOne         80
     i2cmasterSendMult       116
     ??DataTable41             4
     ??DataTable43             4
     ??DataTable45             4
     ??DataTable49             4
     ??DataTable54             4
     ??DataTable55             4
     ??DataTable66             4
     ??DataTable70             4
     ??DataTable71             4
     ??DataTable72             4
     ??DataTable73             4
      Others                  60

 
 3 216 bytes in segment CODE
   183 bytes in segment DATA_Z
    12 bytes in segment INITTAB
 
 3 168 bytes of CODE memory (+ 60 bytes shared)
   183 bytes of DATA memory

Errors: none
Warnings: 2
