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   BITBAND_Peripheral(&(i2c->CTRL),
00292                      _I2C_CTRL_SLAVE_SHIFT,
00293                      init->master? 0 : 1);
00294 
00295   I2C_BusFreqSet(i2c, init->refFreq, init->freq, init->clhr);
00296 
00297   BITBAND_Peripheral(&(i2c->CTRL),
00298                      _I2C_CTRL_EN_SHIFT,
00299                      (unsigned int)(init->enable));
00300 }
00301 
00302 
00303 /***************************************************************************/
00314 void I2C_Reset(I2C_TypeDef *i2c)
00315 {
00316   i2c->CTRL      = _I2C_CTRL_RESETVALUE;
00317   i2c->CLKDIV    = _I2C_CLKDIV_RESETVALUE;
00318   i2c->SADDR     = _I2C_SADDR_RESETVALUE;
00319   i2c->SADDRMASK = _I2C_SADDRMASK_RESETVALUE;
00320   i2c->IEN       = _I2C_IEN_RESETVALUE;
00321   i2c->IFC       = _I2C_IFC_MASK;
00322   /* Do not reset route register, setting should be done independently */
00323 }
00324 
00325 
00326 /***************************************************************************/
00362 I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c)
00363 {
00364   uint32_t                tmp;
00365   uint32_t                pending;
00366   I2C_Transfer_TypeDef    *transfer;
00367   I2C_TransferSeq_TypeDef *seq;
00368 
00369   EFM_ASSERT(I2C_REF_VALID(i2c));
00370 
00371   /* Support up to 2 I2C buses */
00372   if (i2c == I2C0)
00373   {
00374     transfer = i2cTransfer;
00375   }
00376 #if (I2C_COUNT > 1)
00377   else if (i2c == I2C1)
00378   {
00379     transfer = i2cTransfer + 1;
00380   }
00381 #endif
00382   else
00383   {
00384     return(i2cTransferUsageFault);
00385   }
00386 
00387   seq = transfer->seq;
00388   for (;; )
00389   {
00390     pending = i2c->IF;
00391 
00392     /* If some sort of fault, abort transfer. */
00393     if (pending & I2C_IF_ERRORS)
00394     {
00395       if (pending & I2C_IF_ARBLOST)
00396       {
00397         /* If arbitration fault, it indicates either a slave device */
00398         /* not responding as expected, or other master which is not */
00399         /* supported by this SW. */
00400         transfer->result = i2cTransferArbLost;
00401       }
00402       else if (pending & I2C_IF_BUSERR)
00403       {
00404         /* A bus error indicates a misplaced start or stop, which should */
00405         /* not occur in master mode controlled by this SW. */
00406         transfer->result = i2cTransferBusErr;
00407       }
00408 
00409       /* If error situation occurred, it is difficult to know */
00410       /* exact cause and how to resolve. It will be up to a wrapper */
00411       /* to determine how to handle a fault/recovery if possible. */
00412       transfer->state = i2cStateDone;
00413       goto done;
00414     }
00415 
00416     switch (transfer->state)
00417     {
00418     /***************************************************/
00419     /* Send first start+address (first byte if 10 bit) */
00420     /***************************************************/
00421     case i2cStateStartAddrSend:
00422       if (seq->flags & I2C_FLAG_10BIT_ADDR)
00423       {
00424         tmp = (((uint32_t)(seq->addr) >> 8) & 0x06) | 0xf0;
00425 
00426         /* In 10 bit address mode, the address following the first */
00427         /* start always indicate write. */
00428       }
00429       else
00430       {
00431         tmp = (uint32_t)(seq->addr) & 0xfe;
00432 
00433         if (seq->flags & I2C_FLAG_READ)
00434         {
00435           /* Indicate read request */
00436           tmp |= 1;
00437         }
00438       }
00439 
00440       transfer->state = i2cStateAddrWFAckNack;
00441       i2c->TXDATA     = tmp; /* Data not transmitted until START sent */
00442       i2c->CMD        = I2C_CMD_START;
00443       goto done;
00444 
00445     /*******************************************************/
00446     /* Wait for ACK/NACK on address (first byte if 10 bit) */
00447     /*******************************************************/
00448     case i2cStateAddrWFAckNack:
00449       if (pending & I2C_IF_NACK)
00450       {
00451         i2c->IFC         = I2C_IFC_NACK;
00452         transfer->result = i2cTransferNack;
00453         transfer->state  = i2cStateWFStopSent;
00454         i2c->CMD         = I2C_CMD_STOP;
00455       }
00456       else if (pending & I2C_IF_ACK)
00457       {
00458         i2c->IFC = I2C_IFC_ACK;
00459 
00460         /* If 10 bit address, send 2nd byte of address. */
00461         if (seq->flags & I2C_FLAG_10BIT_ADDR)
00462         {
00463           transfer->state = i2cStateAddrWF2ndAckNack;
00464           i2c->TXDATA     = (uint32_t)(seq->addr) & 0xff;
00465         }
00466         else
00467         {
00468           /* Determine whether receiving or sending data */
00469           if (seq->flags & I2C_FLAG_READ)
00470           {
00471             transfer->state = i2cStateWFData;
00472             if(seq->buf[transfer->bufIndx].len==1)
00473             {
00474               i2c->CMD  = I2C_CMD_NACK;
00475             }
00476           }
00477           else
00478           {
00479             transfer->state = i2cStateDataSend;
00480             continue;
00481           }
00482         }
00483       }
00484       goto done;
00485 
00486     /******************************************************/
00487     /* Wait for ACK/NACK on second byte of 10 bit address */
00488     /******************************************************/
00489     case i2cStateAddrWF2ndAckNack:
00490       if (pending & I2C_IF_NACK)
00491       {
00492         i2c->IFC         = I2C_IFC_NACK;
00493         transfer->result = i2cTransferNack;
00494         transfer->state  = i2cStateWFStopSent;
00495         i2c->CMD         = I2C_CMD_STOP;
00496       }
00497       else if (pending & I2C_IF_ACK)
00498       {
00499         i2c->IFC = I2C_IFC_ACK;
00500 
00501         /* If using plain read sequence with 10 bit address, switch to send */
00502         /* repeated start. */
00503         if (seq->flags & I2C_FLAG_READ)
00504         {
00505           transfer->state = i2cStateRStartAddrSend;
00506         }
00507         /* Otherwise expected to write 0 or more bytes */
00508         else
00509         {
00510           transfer->state = i2cStateDataSend;
00511         }
00512         continue;
00513       }
00514       goto done;
00515 
00516     /*******************************/
00517     /* Send repeated start+address */
00518     /*******************************/
00519     case i2cStateRStartAddrSend:
00520       if (seq->flags & I2C_FLAG_10BIT_ADDR)
00521       {
00522         tmp = ((seq->addr >> 8) & 0x06) | 0xf0;
00523       }
00524       else
00525       {
00526         tmp = seq->addr & 0xfe;
00527       }
00528 
00529       /* If this is a write+read combined sequence, then read is about to start */
00530       if (seq->flags & I2C_FLAG_WRITE_READ)
00531       {
00532         /* Indicate read request */
00533         tmp |= 1;
00534       }
00535 
00536       transfer->state = i2cStateRAddrWFAckNack;
00537       /* We have to write START cmd first since repeated start, otherwise */
00538       /* data would be sent first. */
00539       i2c->CMD    = I2C_CMD_START;
00540       i2c->TXDATA = tmp;
00541       goto done;
00542 
00543     /**********************************************************************/
00544     /* Wait for ACK/NACK on repeated start+address (first byte if 10 bit) */
00545     /**********************************************************************/
00546     case i2cStateRAddrWFAckNack:
00547       if (pending & I2C_IF_NACK)
00548       {
00549         i2c->IFC         = I2C_IFC_NACK;
00550         transfer->result = i2cTransferNack;
00551         transfer->state  = i2cStateWFStopSent;
00552         i2c->CMD         = I2C_CMD_STOP;
00553       }
00554       else if (pending & I2C_IF_ACK)
00555       {
00556         i2c->IFC = I2C_IFC_ACK;
00557 
00558         /* Determine whether receiving or sending data */
00559         if (seq->flags & I2C_FLAG_WRITE_READ)
00560         {
00561           transfer->state = i2cStateWFData;
00562         }
00563         else
00564         {
00565           transfer->state = i2cStateDataSend;
00566           continue;
00567         }
00568       }
00569       goto done;
00570 
00571     /*****************************/
00572     /* Send a data byte to slave */
00573     /*****************************/
00574     case i2cStateDataSend:
00575       /* Reached end of data buffer? */
00576       if (transfer->offset >= seq->buf[transfer->bufIndx].len)
00577       {
00578         /* Move to next message part */
00579         transfer->offset = 0;
00580         transfer->bufIndx++;
00581 
00582         /* Send repeated start when switching to read mode on 2nd buffer */
00583         if (seq->flags & I2C_FLAG_WRITE_READ)
00584         {
00585           transfer->state = i2cStateRStartAddrSend;
00586           continue;
00587         }
00588 
00589         /* Only writing from one buffer, or finished both buffers */
00590         if ((seq->flags & I2C_FLAG_WRITE) || (transfer->bufIndx > 1))
00591         {
00592           transfer->state = i2cStateWFStopSent;
00593           i2c->CMD        = I2C_CMD_STOP;
00594           goto done;
00595         }
00596 
00597         /* Reprocess in case next buffer is empty */
00598         continue;
00599       }
00600 
00601       /* Send byte */
00602       i2c->TXDATA     = (uint32_t)(seq->buf[transfer->bufIndx].data[transfer->offset++]);
00603       transfer->state = i2cStateDataWFAckNack;
00604       goto done;
00605 
00606     /*********************************************************/
00607     /* Wait for ACK/NACK from slave after sending data to it */
00608     /*********************************************************/
00609     case i2cStateDataWFAckNack:
00610       if (pending & I2C_IF_NACK)
00611       {
00612         i2c->IFC         = I2C_IFC_NACK;
00613         transfer->result = i2cTransferNack;
00614         transfer->state  = i2cStateWFStopSent;
00615         i2c->CMD         = I2C_CMD_STOP;
00616       }
00617       else if (pending & I2C_IF_ACK)
00618       {
00619         i2c->IFC        = I2C_IFC_ACK;
00620         transfer->state = i2cStateDataSend;
00621         continue;
00622       }
00623       goto done;
00624 
00625     /****************************/
00626     /* Wait for data from slave */
00627     /****************************/
00628     case i2cStateWFData:
00629       if (pending & I2C_IF_RXDATAV)
00630       {
00631         uint8_t       data;
00632         unsigned int  rxLen = seq->buf[transfer->bufIndx].len;
00633 
00634         /* Must read out data in order to not block further progress */
00635         data = (uint8_t)(i2c->RXDATA);
00636 
00637         /* Make sure not storing beyond end of buffer just in case */
00638         if (transfer->offset < rxLen)
00639         {
00640           seq->buf[transfer->bufIndx].data[transfer->offset++] = data;
00641         }
00642 
00643         /* If we have read all requested data, then the sequence should end */
00644         if (transfer->offset >= rxLen)
00645         {
00646           /* If there is only one byte to receive we need to transmit the
00647              NACK now, before the stop. */
00648           if (1 == rxLen)
00649           {
00650             i2c->CMD  = I2C_CMD_NACK;
00651           }
00652             
00653           transfer->state = i2cStateWFStopSent;
00654           i2c->CMD        = I2C_CMD_STOP;
00655         }
00656         else
00657         {
00658           /* Send ACK and wait for next byte */
00659           i2c->CMD = I2C_CMD_ACK;
00660 
00661           if ( (1<rxLen) && (transfer->offset == (rxLen-1)) )
00662           {
00663             /* If there is more than one byte to receive and this is the next
00664                to last byte we need to transmit the NACK now, before receiving
00665                the last byte. */
00666             i2c->CMD  = I2C_CMD_NACK;
00667           }
00668         }
00669       }
00670       goto done;
00671 
00672     /***********************************/
00673     /* Wait for STOP to have been sent */
00674     /***********************************/
00675     case i2cStateWFStopSent:
00676       if (pending & I2C_IF_MSTOP)
00677       {
00678         i2c->IFC        = I2C_IFC_MSTOP;
00679         transfer->state = i2cStateDone;
00680       }
00681       goto done;
00682 
00683     /******************************/
00684     /* Unexpected state, SW fault */
00685     /******************************/
00686     default:
00687       transfer->result = i2cTransferSwFault;
00688       transfer->state  = i2cStateDone;
00689       goto done;
00690     }
00691   }
00692 
00693  done:
00694 
00695   if (transfer->state == i2cStateDone)
00696   {
00697     /* Disable interrupt sources when done */
00698     i2c->IEN = 0;
00699 
00700     /* Update result unless some fault already occurred */
00701     if (transfer->result == i2cTransferInProgress)
00702     {
00703       transfer->result = i2cTransferDone;
00704     }
00705   }
00706   /* Until transfer is done keep returning i2cTransferInProgress */
00707   else
00708   {
00709     return(i2cTransferInProgress);
00710   }
00711 
00712   return transfer->result;
00713 }
00714 
00715 
00716 /***************************************************************************/
00741 I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c,
00742                                             I2C_TransferSeq_TypeDef *seq)
00743 {
00744   I2C_Transfer_TypeDef *transfer;
00745 
00746   EFM_ASSERT(I2C_REF_VALID(i2c));
00747   EFM_ASSERT(seq);
00748 
00749   /* Support up to 2 I2C buses */
00750   if (i2c == I2C0)
00751   {
00752     transfer = i2cTransfer;
00753   }
00754 #if (I2C_COUNT > 1)
00755   else if (i2c == I2C1)
00756   {
00757     transfer = i2cTransfer + 1;
00758   }
00759 #endif
00760   else
00761   {
00762     return(i2cTransferUsageFault);
00763   }
00764 
00765   /* Check if in busy state. Since this SW assumes single master, we can */
00766   /* just issue an abort. The BUSY state is normal after a reset. */
00767   if (i2c->STATE & I2C_STATE_BUSY)
00768   {
00769     i2c->CMD = I2C_CMD_ABORT;
00770   }
00771 
00772   /* Make sure user is not trying to read 0 bytes, it is not */
00773   /* possible according to I2C spec, since slave will always start */
00774   /* sending first byte ACK on address. The read operation can */
00775   /* only be stopped by NACKing a received byte, ie minimum 1 byte. */
00776   if (((seq->flags & I2C_FLAG_READ) && !(seq->buf[0].len)) ||
00777       ((seq->flags & I2C_FLAG_WRITE_READ) && !(seq->buf[1].len))
00778       )
00779   {
00780     return(i2cTransferUsageFault);
00781   }
00782 
00783   /* Prepare for a transfer */
00784   transfer->state   = i2cStateStartAddrSend;
00785   transfer->result  = i2cTransferInProgress;
00786   transfer->offset  = 0;
00787   transfer->bufIndx = 0;
00788   transfer->seq     = seq;
00789 
00790   /* Ensure buffers are empty */
00791   i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
00792   if (i2c->IF & I2C_IF_RXDATAV)
00793   {
00794     (void)i2c->RXDATA;
00795   }
00796 
00797   /* Clear all pending interrupts prior to starting transfer. */
00798   i2c->IFC = _I2C_IFC_MASK;
00799 
00800   /* Enable those interrupts we are interested in throughout transfer. */
00801   /* Notice that the I2C interrupt must also be enabled in the NVIC, but */
00802   /* that is left for an additional driver wrapper. */
00803   i2c->IEN = I2C_IF_NACK | I2C_IF_ACK | I2C_IF_MSTOP |
00804              I2C_IF_RXDATAV | I2C_IF_ERRORS;
00805 
00806   /* Start transfer */
00807   return(I2C_Transfer(i2c));
00808 }
00809 
00812 #endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */