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 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
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
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
00393 if (pending & I2C_IF_ERRORS)
00394 {
00395 if (pending & I2C_IF_ARBLOST)
00396 {
00397
00398
00399
00400 transfer->result = i2cTransferArbLost;
00401 }
00402 else if (pending & I2C_IF_BUSERR)
00403 {
00404
00405
00406 transfer->result = i2cTransferBusErr;
00407 }
00408
00409
00410
00411
00412 transfer->state = i2cStateDone;
00413 goto done;
00414 }
00415
00416 switch (transfer->state)
00417 {
00418
00419
00420
00421 case i2cStateStartAddrSend:
00422 if (seq->flags & I2C_FLAG_10BIT_ADDR)
00423 {
00424 tmp = (((uint32_t)(seq->addr) >> 8) & 0x06) | 0xf0;
00425
00426
00427
00428 }
00429 else
00430 {
00431 tmp = (uint32_t)(seq->addr) & 0xfe;
00432
00433 if (seq->flags & I2C_FLAG_READ)
00434 {
00435
00436 tmp |= 1;
00437 }
00438 }
00439
00440 transfer->state = i2cStateAddrWFAckNack;
00441 i2c->TXDATA = tmp;
00442 i2c->CMD = I2C_CMD_START;
00443 goto done;
00444
00445
00446
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
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
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
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
00502
00503 if (seq->flags & I2C_FLAG_READ)
00504 {
00505 transfer->state = i2cStateRStartAddrSend;
00506 }
00507
00508 else
00509 {
00510 transfer->state = i2cStateDataSend;
00511 }
00512 continue;
00513 }
00514 goto done;
00515
00516
00517
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
00530 if (seq->flags & I2C_FLAG_WRITE_READ)
00531 {
00532
00533 tmp |= 1;
00534 }
00535
00536 transfer->state = i2cStateRAddrWFAckNack;
00537
00538
00539 i2c->CMD = I2C_CMD_START;
00540 i2c->TXDATA = tmp;
00541 goto done;
00542
00543
00544
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
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
00573
00574 case i2cStateDataSend:
00575
00576 if (transfer->offset >= seq->buf[transfer->bufIndx].len)
00577 {
00578
00579 transfer->offset = 0;
00580 transfer->bufIndx++;
00581
00582
00583 if (seq->flags & I2C_FLAG_WRITE_READ)
00584 {
00585 transfer->state = i2cStateRStartAddrSend;
00586 continue;
00587 }
00588
00589
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
00598 continue;
00599 }
00600
00601
00602 i2c->TXDATA = (uint32_t)(seq->buf[transfer->bufIndx].data[transfer->offset++]);
00603 transfer->state = i2cStateDataWFAckNack;
00604 goto done;
00605
00606
00607
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
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
00635 data = (uint8_t)(i2c->RXDATA);
00636
00637
00638 if (transfer->offset < rxLen)
00639 {
00640 seq->buf[transfer->bufIndx].data[transfer->offset++] = data;
00641 }
00642
00643
00644 if (transfer->offset >= rxLen)
00645 {
00646
00647
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
00659 i2c->CMD = I2C_CMD_ACK;
00660
00661 if ( (1<rxLen) && (transfer->offset == (rxLen-1)) )
00662 {
00663
00664
00665
00666 i2c->CMD = I2C_CMD_NACK;
00667 }
00668 }
00669 }
00670 goto done;
00671
00672
00673
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
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
00698 i2c->IEN = 0;
00699
00700
00701 if (transfer->result == i2cTransferInProgress)
00702 {
00703 transfer->result = i2cTransferDone;
00704 }
00705 }
00706
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
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
00766
00767 if (i2c->STATE & I2C_STATE_BUSY)
00768 {
00769 i2c->CMD = I2C_CMD_ABORT;
00770 }
00771
00772
00773
00774
00775
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
00784 transfer->state = i2cStateStartAddrSend;
00785 transfer->result = i2cTransferInProgress;
00786 transfer->offset = 0;
00787 transfer->bufIndx = 0;
00788 transfer->seq = seq;
00789
00790
00791 i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
00792 if (i2c->IF & I2C_IF_RXDATAV)
00793 {
00794 (void)i2c->RXDATA;
00795 }
00796
00797
00798 i2c->IFC = _I2C_IFC_MASK;
00799
00800
00801
00802
00803 i2c->IEN = I2C_IF_NACK | I2C_IF_ACK | I2C_IF_MSTOP |
00804 I2C_IF_RXDATAV | I2C_IF_ERRORS;
00805
00806
00807 return(I2C_Transfer(i2c));
00808 }
00809
00812 #endif