em_i2c.c

Go to the documentation of this file.
00001 /***************************************************************************/
00034 #include "em_i2c.h"
00035 #if defined(I2C_COUNT) && (I2C_COUNT > 0)
00036 
00037 #include "em_cmu.h"
00038 #include "em_bitband.h"
00039 #include "em_assert.h"
00040 
00041 /***************************************************************************/
00046 /***************************************************************************/
00052 /*******************************************************************************
00053  *******************************   DEFINES   ***********************************
00054  ******************************************************************************/
00055 
00058 #if (I2C_COUNT == 1)
00059 
00060 #define I2C_REF_VALID(ref)    ((ref) == I2C0)
00061 
00062 #elif (I2C_COUNT == 2)
00063 
00064 #define I2C_REF_VALID(ref)    ((ref == I2C0) || (ref == I2C1))
00065 #endif
00066 
00068 /* Notice that I2C_IF_TXOF (transmit overflow) is not really possible with */
00069 /* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive underflow) */
00070 /* RXUF is only likely to occur with this SW if using a debugger peeking into */
00071 /* RXDATA register. Thus, we ignore those types of fault. */
00072 #define I2C_IF_ERRORS    (I2C_IF_BUSERR | I2C_IF_ARBLOST)
00073 
00076 /*******************************************************************************
00077  ********************************   ENUMS   ************************************
00078  ******************************************************************************/
00079 
00083 typedef enum
00084 {
00085   i2cStateStartAddrSend,       
00086   i2cStateAddrWFAckNack,       
00087   i2cStateAddrWF2ndAckNack,    
00088   i2cStateRStartAddrSend,      
00089   i2cStateRAddrWFAckNack,      
00090   i2cStateDataSend,            
00091   i2cStateDataWFAckNack,       
00092   i2cStateWFData,              
00093   i2cStateWFStopSent,          
00094   i2cStateDone                 
00095 } I2C_TransferState_TypeDef;
00096 
00099 /*******************************************************************************
00100  *******************************   STRUCTS   ***********************************
00101  ******************************************************************************/
00102 
00106 typedef struct
00107 {
00109   I2C_TransferState_TypeDef  state;
00110 
00112   I2C_TransferReturn_TypeDef result;
00113 
00115   uint16_t                   offset;
00116 
00117   /* Index to current sequence buffer in use. */
00118   uint8_t                    bufIndx;
00119 
00121   I2C_TransferSeq_TypeDef    *seq;
00122 } I2C_Transfer_TypeDef;
00123 
00126 /*******************************************************************************
00127  *****************************   LOCAL DATA   *******^**************************
00128  ******************************************************************************/
00129 
00136 static const uint8_t i2cNSum[] = { 4 + 4, 6 + 3, 11 + 6, 4 + 4 };
00137 
00139 static I2C_Transfer_TypeDef i2cTransfer[I2C_COUNT];
00140 
00143 /*******************************************************************************
00144  **************************   GLOBAL FUNCTIONS   *******************************
00145  ******************************************************************************/
00146 
00147 /***************************************************************************/
00160 uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c)
00161 {
00162   uint32_t hfperclk;
00163   uint32_t n;
00164 
00165   /* Max frequency is given by fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4) */
00166   hfperclk = CMU_ClockFreqGet(cmuClock_HFPER);
00167   n        = (uint32_t)(i2cNSum[(i2c->CTRL & _I2C_CTRL_CLHR_MASK) >> _I2C_CTRL_CLHR_SHIFT]);
00168 
00169   return(hfperclk / ((n * (i2c->CLKDIV + 1)) + 4));
00170 }
00171 
00172 
00173 /***************************************************************************/
00211 void I2C_BusFreqSet(I2C_TypeDef *i2c,
00212                     uint32_t refFreq,
00213                     uint32_t freq,
00214                     I2C_ClockHLR_TypeDef type)
00215 {
00216   uint32_t n;
00217   uint32_t div;
00218 
00219   /* Avoid divide by 0 */
00220   EFM_ASSERT(freq);
00221   if (!freq)
00222   {
00223     return;
00224   }
00225 
00226   /* Set the CLHR (clock low to high ratio). */
00227   i2c->CTRL &= ~_I2C_CTRL_CLHR_MASK;
00228   i2c->CTRL |= type <<_I2C_CTRL_CLHR_SHIFT;
00229 
00230   /* Frequency is given by fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4), thus */
00231   /* DIV = ((fHFPERCLK - 4fSCL)/((Nlow + Nhigh)fSCL)) - 1 */
00232 
00233   if (!refFreq)
00234   {
00235     refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
00236   }
00237   n = (uint32_t)(i2cNSum[type]);
00238 
00239   div = (refFreq - (4 * freq)) / (n * freq);
00240 
00241   /* Clock divisor must be at least 1 in slave mode according to reference */
00242   /* manual (in which case there is normally no need to set bus frequency). */
00243   if ((i2c->CTRL & I2C_CTRL_SLAVE) && !div)
00244   {
00245     div = 1;
00246   }
00247 
00248   EFM_ASSERT(div <= _I2C_CLKDIV_DIV_MASK);
00249   i2c->CLKDIV = div;
00250 }
00251 
00252 
00253 /***************************************************************************/
00266 void I2C_Enable(I2C_TypeDef *i2c, bool enable)
00267 {
00268   EFM_ASSERT(I2C_REF_VALID(i2c));
00269 
00270   BITBAND_Peripheral(&(i2c->CTRL), _I2C_CTRL_EN_SHIFT, (unsigned int)enable);
00271 }
00272 
00273 
00274 /***************************************************************************/
00284 void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init)
00285 {
00286   EFM_ASSERT(I2C_REF_VALID(i2c));
00287 
00288   i2c->IEN = 0;
00289   i2c->IFC = _I2C_IFC_MASK;
00290 
00291   /* Set SLAVE select mode */
00292   BITBAND_Peripheral(&(i2c->CTRL),
00293                      _I2C_CTRL_SLAVE_SHIFT,
00294                      init->master ? 0 : 1);
00295 
00296   I2C_BusFreqSet(i2c, init->refFreq, init->freq, init->clhr);
00297 
00298   BITBAND_Peripheral(&(i2c->CTRL),
00299                      _I2C_CTRL_EN_SHIFT,
00300                      (unsigned int)(init->enable));
00301 }
00302 
00303 
00304 /***************************************************************************/
00315 void I2C_Reset(I2C_TypeDef *i2c)
00316 {
00317   i2c->CTRL      = _I2C_CTRL_RESETVALUE;
00318   i2c->CLKDIV    = _I2C_CLKDIV_RESETVALUE;
00319   i2c->SADDR     = _I2C_SADDR_RESETVALUE;
00320   i2c->SADDRMASK = _I2C_SADDRMASK_RESETVALUE;
00321   i2c->IEN       = _I2C_IEN_RESETVALUE;
00322   i2c->IFC       = _I2C_IFC_MASK;
00323   /* Do not reset route register, setting should be done independently */
00324 }
00325 
00326 
00327 /***************************************************************************/
00363 I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c)
00364 {
00365   uint32_t                tmp;
00366   uint32_t                pending;
00367   I2C_Transfer_TypeDef    *transfer;
00368   I2C_TransferSeq_TypeDef *seq;
00369 
00370   EFM_ASSERT(I2C_REF_VALID(i2c));
00371 
00372   /* Support up to 2 I2C buses */
00373   if (i2c == I2C0)
00374   {
00375     transfer = i2cTransfer;
00376   }
00377 #if (I2C_COUNT > 1)
00378   else if (i2c == I2C1)
00379   {
00380     transfer = i2cTransfer + 1;
00381   }
00382 #endif
00383   else
00384   {
00385     return(i2cTransferUsageFault);
00386   }
00387 
00388   seq = transfer->seq;
00389   for (;; )
00390   {
00391     pending = i2c->IF;
00392 
00393     /* If some sort of fault, abort transfer. */
00394     if (pending & I2C_IF_ERRORS)
00395     {
00396       if (pending & I2C_IF_ARBLOST)
00397       {
00398         /* If arbitration fault, it indicates either a slave device */
00399         /* not responding as expected, or other master which is not */
00400         /* supported by this SW. */
00401         transfer->result = i2cTransferArbLost;
00402       }
00403       else if (pending & I2C_IF_BUSERR)
00404       {
00405         /* A bus error indicates a misplaced start or stop, which should */
00406         /* not occur in master mode controlled by this SW. */
00407         transfer->result = i2cTransferBusErr;
00408       }
00409 
00410       /* If error situation occurred, it is difficult to know */
00411       /* exact cause and how to resolve. It will be up to a wrapper */
00412       /* to determine how to handle a fault/recovery if possible. */
00413       transfer->state = i2cStateDone;
00414       goto done;
00415     }
00416 
00417     switch (transfer->state)
00418     {
00419     /***************************************************/
00420     /* Send first start+address (first byte if 10 bit) */
00421     /***************************************************/
00422     case i2cStateStartAddrSend:
00423       if (seq->flags & I2C_FLAG_10BIT_ADDR)
00424       {
00425         tmp = (((uint32_t)(seq->addr) >> 8) & 0x06) | 0xf0;
00426 
00427         /* In 10 bit address mode, the address following the first */
00428         /* start always indicate write. */
00429       }
00430       else
00431       {
00432         tmp = (uint32_t)(seq->addr) & 0xfe;
00433 
00434         if (seq->flags & I2C_FLAG_READ)
00435         {
00436           /* Indicate read request */
00437           tmp |= 1;
00438         }
00439       }
00440 
00441       transfer->state = i2cStateAddrWFAckNack;
00442       i2c->TXDATA     = tmp; /* Data not transmitted until START sent */
00443       i2c->CMD        = I2C_CMD_START;
00444       goto done;
00445 
00446     /*******************************************************/
00447     /* Wait for ACK/NACK on address (first byte if 10 bit) */
00448     /*******************************************************/
00449     case i2cStateAddrWFAckNack:
00450       if (pending & I2C_IF_NACK)
00451       {
00452         i2c->IFC         = I2C_IFC_NACK;
00453         transfer->result = i2cTransferNack;
00454         transfer->state  = i2cStateWFStopSent;
00455         i2c->CMD         = I2C_CMD_STOP;
00456       }
00457       else if (pending & I2C_IF_ACK)
00458       {
00459         i2c->IFC = I2C_IFC_ACK;
00460 
00461         /* If 10 bit address, send 2nd byte of address. */
00462         if (seq->flags & I2C_FLAG_10BIT_ADDR)
00463         {
00464           transfer->state = i2cStateAddrWF2ndAckNack;
00465           i2c->TXDATA     = (uint32_t)(seq->addr) & 0xff;
00466         }
00467         else
00468         {
00469           /* Determine whether receiving or sending data */
00470           if (seq->flags & I2C_FLAG_READ)
00471           {
00472             transfer->state = i2cStateWFData;
00473             if(seq->buf[transfer->bufIndx].len==1)
00474             {
00475               i2c->CMD  = I2C_CMD_NACK;
00476             }
00477           }
00478           else
00479           {
00480             transfer->state = i2cStateDataSend;
00481             continue;
00482           }
00483         }
00484       }
00485       goto done;
00486 
00487     /******************************************************/
00488     /* Wait for ACK/NACK on second byte of 10 bit address */
00489     /******************************************************/
00490     case i2cStateAddrWF2ndAckNack:
00491       if (pending & I2C_IF_NACK)
00492       {
00493         i2c->IFC         = I2C_IFC_NACK;
00494         transfer->result = i2cTransferNack;
00495         transfer->state  = i2cStateWFStopSent;
00496         i2c->CMD         = I2C_CMD_STOP;
00497       }
00498       else if (pending & I2C_IF_ACK)
00499       {
00500         i2c->IFC = I2C_IFC_ACK;
00501 
00502         /* If using plain read sequence with 10 bit address, switch to send */
00503         /* repeated start. */
00504         if (seq->flags & I2C_FLAG_READ)
00505         {
00506           transfer->state = i2cStateRStartAddrSend;
00507         }
00508         /* Otherwise expected to write 0 or more bytes */
00509         else
00510         {
00511           transfer->state = i2cStateDataSend;
00512         }
00513         continue;
00514       }
00515       goto done;
00516 
00517     /*******************************/
00518     /* Send repeated start+address */
00519     /*******************************/
00520     case i2cStateRStartAddrSend:
00521       if (seq->flags & I2C_FLAG_10BIT_ADDR)
00522       {
00523         tmp = ((seq->addr >> 8) & 0x06) | 0xf0;
00524       }
00525       else
00526       {
00527         tmp = seq->addr & 0xfe;
00528       }
00529 
00530       /* If this is a write+read combined sequence, then read is about to start */
00531       if (seq->flags & I2C_FLAG_WRITE_READ)
00532       {
00533         /* Indicate read request */
00534         tmp |= 1;
00535       }
00536 
00537       transfer->state = i2cStateRAddrWFAckNack;
00538       /* We have to write START cmd first since repeated start, otherwise */
00539       /* data would be sent first. */
00540       i2c->CMD    = I2C_CMD_START;
00541       i2c->TXDATA = tmp;
00542       goto done;
00543 
00544     /**********************************************************************/
00545     /* Wait for ACK/NACK on repeated start+address (first byte if 10 bit) */
00546     /**********************************************************************/
00547     case i2cStateRAddrWFAckNack:
00548       if (pending & I2C_IF_NACK)
00549       {
00550         i2c->IFC         = I2C_IFC_NACK;
00551         transfer->result = i2cTransferNack;
00552         transfer->state  = i2cStateWFStopSent;
00553         i2c->CMD         = I2C_CMD_STOP;
00554       }
00555       else if (pending & I2C_IF_ACK)
00556       {
00557         i2c->IFC = I2C_IFC_ACK;
00558 
00559         /* Determine whether receiving or sending data */
00560         if (seq->flags & I2C_FLAG_WRITE_READ)
00561         {
00562           transfer->state = i2cStateWFData;
00563         }
00564         else
00565         {
00566           transfer->state = i2cStateDataSend;
00567           continue;
00568         }
00569       }
00570       goto done;
00571 
00572     /*****************************/
00573     /* Send a data byte to slave */
00574     /*****************************/
00575     case i2cStateDataSend:
00576       /* Reached end of data buffer? */
00577       if (transfer->offset >= seq->buf[transfer->bufIndx].len)
00578       {
00579         /* Move to next message part */
00580         transfer->offset = 0;
00581         transfer->bufIndx++;
00582 
00583         /* Send repeated start when switching to read mode on 2nd buffer */
00584         if (seq->flags & I2C_FLAG_WRITE_READ)
00585         {
00586           transfer->state = i2cStateRStartAddrSend;
00587           continue;
00588         }
00589 
00590         /* Only writing from one buffer, or finished both buffers */
00591         if ((seq->flags & I2C_FLAG_WRITE) || (transfer->bufIndx > 1))
00592         {
00593           transfer->state = i2cStateWFStopSent;
00594           i2c->CMD        = I2C_CMD_STOP;
00595           goto done;
00596         }
00597 
00598         /* Reprocess in case next buffer is empty */
00599         continue;
00600       }
00601 
00602       /* Send byte */
00603       i2c->TXDATA     = (uint32_t)(seq->buf[transfer->bufIndx].data[transfer->offset++]);
00604       transfer->state = i2cStateDataWFAckNack;
00605       goto done;
00606 
00607     /*********************************************************/
00608     /* Wait for ACK/NACK from slave after sending data to it */
00609     /*********************************************************/
00610     case i2cStateDataWFAckNack:
00611       if (pending & I2C_IF_NACK)
00612       {
00613         i2c->IFC         = I2C_IFC_NACK;
00614         transfer->result = i2cTransferNack;
00615         transfer->state  = i2cStateWFStopSent;
00616         i2c->CMD         = I2C_CMD_STOP;
00617       }
00618       else if (pending & I2C_IF_ACK)
00619       {
00620         i2c->IFC        = I2C_IFC_ACK;
00621         transfer->state = i2cStateDataSend;
00622         continue;
00623       }
00624       goto done;
00625 
00626     /****************************/
00627     /* Wait for data from slave */
00628     /****************************/
00629     case i2cStateWFData:
00630       if (pending & I2C_IF_RXDATAV)
00631       {
00632         uint8_t       data;
00633         unsigned int  rxLen = seq->buf[transfer->bufIndx].len;
00634 
00635         /* Must read out data in order to not block further progress */
00636         data = (uint8_t)(i2c->RXDATA);
00637 
00638         /* Make sure not storing beyond end of buffer just in case */
00639         if (transfer->offset < rxLen)
00640         {
00641           seq->buf[transfer->bufIndx].data[transfer->offset++] = data;
00642         }
00643 
00644         /* If we have read all requested data, then the sequence should end */
00645         if (transfer->offset >= rxLen)
00646         {
00647           /* If there is only one byte to receive we need to transmit the
00648              NACK now, before the stop. */
00649           if (1 == rxLen)
00650           {
00651             i2c->CMD  = I2C_CMD_NACK;
00652           }
00653 
00654           transfer->state = i2cStateWFStopSent;
00655           i2c->CMD        = I2C_CMD_STOP;
00656         }
00657         else
00658         {
00659           /* Send ACK and wait for next byte */
00660           i2c->CMD = I2C_CMD_ACK;
00661 
00662           if ( (1<rxLen) && (transfer->offset == (rxLen-1)) )
00663           {
00664             /* If there is more than one byte to receive and this is the next
00665                to last byte we need to transmit the NACK now, before receiving
00666                the last byte. */
00667             i2c->CMD  = I2C_CMD_NACK;
00668           }
00669         }
00670       }
00671       goto done;
00672 
00673     /***********************************/
00674     /* Wait for STOP to have been sent */
00675     /***********************************/
00676     case i2cStateWFStopSent:
00677       if (pending & I2C_IF_MSTOP)
00678       {
00679         i2c->IFC        = I2C_IFC_MSTOP;
00680         transfer->state = i2cStateDone;
00681       }
00682       goto done;
00683 
00684     /******************************/
00685     /* Unexpected state, SW fault */
00686     /******************************/
00687     default:
00688       transfer->result = i2cTransferSwFault;
00689       transfer->state  = i2cStateDone;
00690       goto done;
00691     }
00692   }
00693 
00694  done:
00695 
00696   if (transfer->state == i2cStateDone)
00697   {
00698     /* Disable interrupt sources when done */
00699     i2c->IEN = 0;
00700 
00701     /* Update result unless some fault already occurred */
00702     if (transfer->result == i2cTransferInProgress)
00703     {
00704       transfer->result = i2cTransferDone;
00705     }
00706   }
00707   /* Until transfer is done keep returning i2cTransferInProgress */
00708   else
00709   {
00710     return(i2cTransferInProgress);
00711   }
00712 
00713   return transfer->result;
00714 }
00715 
00716 
00717 /***************************************************************************/
00742 I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c,
00743                                             I2C_TransferSeq_TypeDef *seq)
00744 {
00745   I2C_Transfer_TypeDef *transfer;
00746 
00747   EFM_ASSERT(I2C_REF_VALID(i2c));
00748   EFM_ASSERT(seq);
00749 
00750   /* Support up to 2 I2C buses */
00751   if (i2c == I2C0)
00752   {
00753     transfer = i2cTransfer;
00754   }
00755 #if (I2C_COUNT > 1)
00756   else if (i2c == I2C1)
00757   {
00758     transfer = i2cTransfer + 1;
00759   }
00760 #endif
00761   else
00762   {
00763     return(i2cTransferUsageFault);
00764   }
00765 
00766   /* Check if in busy state. Since this SW assumes single master, we can */
00767   /* just issue an abort. The BUSY state is normal after a reset. */
00768   if (i2c->STATE & I2C_STATE_BUSY)
00769   {
00770     i2c->CMD = I2C_CMD_ABORT;
00771   }
00772 
00773   /* Make sure user is not trying to read 0 bytes, it is not */
00774   /* possible according to I2C spec, since slave will always start */
00775   /* sending first byte ACK on address. The read operation can */
00776   /* only be stopped by NACKing a received byte, ie minimum 1 byte. */
00777   if (((seq->flags & I2C_FLAG_READ) && !(seq->buf[0].len)) ||
00778       ((seq->flags & I2C_FLAG_WRITE_READ) && !(seq->buf[1].len))
00779       )
00780   {
00781     return(i2cTransferUsageFault);
00782   }
00783 
00784   /* Prepare for a transfer */
00785   transfer->state   = i2cStateStartAddrSend;
00786   transfer->result  = i2cTransferInProgress;
00787   transfer->offset  = 0;
00788   transfer->bufIndx = 0;
00789   transfer->seq     = seq;
00790 
00791   /* Ensure buffers are empty */
00792   i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
00793   if (i2c->IF & I2C_IF_RXDATAV)
00794   {
00795     (void)i2c->RXDATA;
00796   }
00797 
00798   /* Clear all pending interrupts prior to starting transfer. */
00799   i2c->IFC = _I2C_IFC_MASK;
00800 
00801   /* Enable those interrupts we are interested in throughout transfer. */
00802   /* Notice that the I2C interrupt must also be enabled in the NVIC, but */
00803   /* that is left for an additional driver wrapper. */
00804   i2c->IEN = I2C_IF_NACK | I2C_IF_ACK | I2C_IF_MSTOP |
00805              I2C_IF_RXDATAV | I2C_IF_ERRORS;
00806 
00807   /* Start transfer */
00808   return(I2C_Transfer(i2c));
00809 }
00810 
00813 #endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */