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
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
00069
00070
00071
00072 #define I2C_IF_ERRORS (I2C_IF_BUSERR | I2C_IF_ARBLOST)
00073
00076
00077
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
00101
00102
00106 typedef struct
00107 {
00109 I2C_TransferState_TypeDef state;
00110
00112 I2C_TransferReturn_TypeDef result;
00113
00115 uint16_t offset;
00116
00117
00118 uint8_t bufIndx;
00119
00121 I2C_TransferSeq_TypeDef *seq;
00122 } I2C_Transfer_TypeDef;
00123
00126
00127
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
00145
00146
00147
00160 uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c)
00161 {
00162 uint32_t hfperclk;
00163 uint32_t n;
00164
00165
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
00220 EFM_ASSERT(freq);
00221 if (!freq)
00222 {
00223 return;
00224 }
00225
00226
00227 i2c->CTRL &= ~_I2C_CTRL_CLHR_MASK;
00228 i2c->CTRL |= type <<_I2C_CTRL_CLHR_SHIFT;
00229
00230
00231
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
00242
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
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
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
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
00394 if (pending & I2C_IF_ERRORS)
00395 {
00396 if (pending & I2C_IF_ARBLOST)
00397 {
00398
00399
00400
00401 transfer->result = i2cTransferArbLost;
00402 }
00403 else if (pending & I2C_IF_BUSERR)
00404 {
00405
00406
00407 transfer->result = i2cTransferBusErr;
00408 }
00409
00410
00411
00412
00413 transfer->state = i2cStateDone;
00414 goto done;
00415 }
00416
00417 switch (transfer->state)
00418 {
00419
00420
00421
00422 case i2cStateStartAddrSend:
00423 if (seq->flags & I2C_FLAG_10BIT_ADDR)
00424 {
00425 tmp = (((uint32_t)(seq->addr) >> 8) & 0x06) | 0xf0;
00426
00427
00428
00429 }
00430 else
00431 {
00432 tmp = (uint32_t)(seq->addr) & 0xfe;
00433
00434 if (seq->flags & I2C_FLAG_READ)
00435 {
00436
00437 tmp |= 1;
00438 }
00439 }
00440
00441 transfer->state = i2cStateAddrWFAckNack;
00442 i2c->TXDATA = tmp;
00443 i2c->CMD = I2C_CMD_START;
00444 goto done;
00445
00446
00447
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
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
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
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
00503
00504 if (seq->flags & I2C_FLAG_READ)
00505 {
00506 transfer->state = i2cStateRStartAddrSend;
00507 }
00508
00509 else
00510 {
00511 transfer->state = i2cStateDataSend;
00512 }
00513 continue;
00514 }
00515 goto done;
00516
00517
00518
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
00531 if (seq->flags & I2C_FLAG_WRITE_READ)
00532 {
00533
00534 tmp |= 1;
00535 }
00536
00537 transfer->state = i2cStateRAddrWFAckNack;
00538
00539
00540 i2c->CMD = I2C_CMD_START;
00541 i2c->TXDATA = tmp;
00542 goto done;
00543
00544
00545
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
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
00574
00575 case i2cStateDataSend:
00576
00577 if (transfer->offset >= seq->buf[transfer->bufIndx].len)
00578 {
00579
00580 transfer->offset = 0;
00581 transfer->bufIndx++;
00582
00583
00584 if (seq->flags & I2C_FLAG_WRITE_READ)
00585 {
00586 transfer->state = i2cStateRStartAddrSend;
00587 continue;
00588 }
00589
00590
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
00599 continue;
00600 }
00601
00602
00603 i2c->TXDATA = (uint32_t)(seq->buf[transfer->bufIndx].data[transfer->offset++]);
00604 transfer->state = i2cStateDataWFAckNack;
00605 goto done;
00606
00607
00608
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
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
00636 data = (uint8_t)(i2c->RXDATA);
00637
00638
00639 if (transfer->offset < rxLen)
00640 {
00641 seq->buf[transfer->bufIndx].data[transfer->offset++] = data;
00642 }
00643
00644
00645 if (transfer->offset >= rxLen)
00646 {
00647
00648
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
00660 i2c->CMD = I2C_CMD_ACK;
00661
00662 if ( (1<rxLen) && (transfer->offset == (rxLen-1)) )
00663 {
00664
00665
00666
00667 i2c->CMD = I2C_CMD_NACK;
00668 }
00669 }
00670 }
00671 goto done;
00672
00673
00674
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
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
00699 i2c->IEN = 0;
00700
00701
00702 if (transfer->result == i2cTransferInProgress)
00703 {
00704 transfer->result = i2cTransferDone;
00705 }
00706 }
00707
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
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
00767
00768 if (i2c->STATE & I2C_STATE_BUSY)
00769 {
00770 i2c->CMD = I2C_CMD_ABORT;
00771 }
00772
00773
00774
00775
00776
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
00785 transfer->state = i2cStateStartAddrSend;
00786 transfer->result = i2cTransferInProgress;
00787 transfer->offset = 0;
00788 transfer->bufIndx = 0;
00789 transfer->seq = seq;
00790
00791
00792 i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
00793 if (i2c->IF & I2C_IF_RXDATAV)
00794 {
00795 (void)i2c->RXDATA;
00796 }
00797
00798
00799 i2c->IFC = _I2C_IFC_MASK;
00800
00801
00802
00803
00804 i2c->IEN = I2C_IF_NACK | I2C_IF_ACK | I2C_IF_MSTOP |
00805 I2C_IF_RXDATAV | I2C_IF_ERRORS;
00806
00807
00808 return(I2C_Transfer(i2c));
00809 }
00810
00813 #endif