em_usart.c
Go to the documentation of this file.00001
00035 #include "em_usart.h"
00036 #if defined(USART_COUNT) && (USART_COUNT > 0)
00037
00038 #include "em_cmu.h"
00039 #include "em_assert.h"
00040
00041
00046
00053
00054
00055
00056
00061 #if (USART_COUNT == 1) && defined(USART0)
00062 #define USART_REF_VALID(ref) ((ref) == USART0)
00063
00064 #elif (USART_COUNT == 1) && defined(USART1)
00065 #define USART_REF_VALID(ref) ((ref) == USART1)
00066
00067 #elif (USART_COUNT == 2)
00068 #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1))
00069
00070 #elif (USART_COUNT == 3)
00071 #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1) || \
00072 ((ref) == USART2))
00073 #elif (USART_COUNT == 4)
00074 #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1) || \
00075 ((ref) == USART2) || ((ref) == USART3))
00076 #else
00077 #error Undefined number of USARTs.
00078 #endif
00079
00080 #if defined(USART0)
00081 #define USART_IRDA_VALID(ref) ((ref) == USART0)
00082 #elif (USART_COUNT == 1) && defined(USART1)
00083 #define USART_IRDA_VALID(ref) ((ref) == USART1)
00084 #else
00085 #define USART_IRDA_VALID(ref) (0)
00086 #endif
00087
00088 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_ZERO_FAMILY)
00089 #define USART_I2S_VALID(ref) ((ref) == USART1)
00090
00091 #elif defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00092 #define USART_I2S_VALID(ref) (((ref) == USART1) || ((ref) == USART2))
00093 #endif
00094
00095 #if (UART_COUNT == 1)
00096 #define UART_REF_VALID(ref) ((ref) == UART0)
00097 #elif (UART_COUNT == 2)
00098 #define UART_REF_VALID(ref) (((ref) == UART0) || ((ref) == UART1))
00099 #else
00100 #define UART_REF_VALID(ref) (0)
00101 #endif
00102
00106
00107
00108
00109
00110
00132 void USART_BaudrateAsyncSet(USART_TypeDef *usart,
00133 uint32_t refFreq,
00134 uint32_t baudrate,
00135 USART_OVS_TypeDef ovs)
00136 {
00137 uint32_t clkdiv;
00138 uint32_t oversample;
00139
00140
00141 EFM_ASSERT(baudrate);
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 if (!refFreq)
00171 {
00172 refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
00173 }
00174
00175
00176 switch (ovs)
00177 {
00178 case USART_CTRL_OVS_X16:
00179 EFM_ASSERT(baudrate <= (refFreq / 16));
00180 oversample = 16;
00181 break;
00182
00183 case USART_CTRL_OVS_X8:
00184 EFM_ASSERT(baudrate <= (refFreq / 8));
00185 oversample = 8;
00186 break;
00187
00188 case USART_CTRL_OVS_X6:
00189 EFM_ASSERT(baudrate <= (refFreq / 6));
00190 oversample = 6;
00191 break;
00192
00193 case USART_CTRL_OVS_X4:
00194 EFM_ASSERT(baudrate <= (refFreq / 4));
00195 oversample = 4;
00196 break;
00197
00198 default:
00199
00200 EFM_ASSERT(0);
00201 return;
00202 }
00203
00204
00205
00206
00207
00208
00209 clkdiv = 4 * refFreq + (oversample * baudrate) / 2;
00210 clkdiv /= (oversample * baudrate);
00211 clkdiv -= 4;
00212 clkdiv *= 64;
00213
00214
00215 EFM_ASSERT(clkdiv <= _USART_CLKDIV_MASK);
00216
00217
00218 clkdiv &= _USART_CLKDIV_MASK;
00219
00220 usart->CTRL &= ~_USART_CTRL_OVS_MASK;
00221 usart->CTRL |= ovs;
00222 usart->CLKDIV = clkdiv;
00223 }
00224
00225
00226
00254 uint32_t USART_BaudrateCalc(uint32_t refFreq,
00255 uint32_t clkdiv,
00256 bool syncmode,
00257 USART_OVS_TypeDef ovs)
00258 {
00259 uint32_t oversample;
00260 uint32_t divisor;
00261 uint32_t factor;
00262 uint32_t remainder;
00263 uint32_t quotient;
00264 uint32_t br;
00265
00266
00267 clkdiv &= _USART_CLKDIV_MASK;
00268
00269
00270
00271
00272
00273 if (syncmode)
00274 {
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 oversample = 1;
00285 factor = 128;
00286 }
00287 else
00288 {
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 switch (ovs)
00303 {
00304 case USART_CTRL_OVS_X16:
00305 oversample = 1;
00306 factor = 256 / 16;
00307 break;
00308
00309 case USART_CTRL_OVS_X8:
00310 oversample = 1;
00311 factor = 256 / 8;
00312 break;
00313
00314 case USART_CTRL_OVS_X6:
00315 oversample = 3;
00316 factor = 256 / 2;
00317 break;
00318
00319 default:
00320 oversample = 1;
00321 factor = 256 / 4;
00322 break;
00323 }
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 divisor = oversample * (256 + clkdiv);
00350
00351 quotient = refFreq / divisor;
00352 remainder = refFreq % divisor;
00353
00354
00355
00356 br = factor * quotient;
00357
00358
00359
00360
00361
00362
00363 br += (factor * remainder) / divisor;
00364
00365 return br;
00366 }
00367
00368
00369
00383 uint32_t USART_BaudrateGet(USART_TypeDef *usart)
00384 {
00385 uint32_t freq;
00386 USART_OVS_TypeDef ovs;
00387 bool syncmode;
00388
00389 if (usart->CTRL & USART_CTRL_SYNC)
00390 {
00391 syncmode = true;
00392 }
00393 else
00394 {
00395 syncmode = false;
00396 }
00397
00398
00399 freq = CMU_ClockFreqGet(cmuClock_HFPER);
00400 ovs = (USART_OVS_TypeDef) (usart->CTRL & _USART_CTRL_OVS_MASK);
00401 return USART_BaudrateCalc(freq, usart->CLKDIV, syncmode, ovs);
00402 }
00403
00404
00405
00432 void USART_BaudrateSyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate)
00433 {
00434 uint32_t clkdiv;
00435
00436
00437 EFM_ASSERT(baudrate);
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 if (!refFreq)
00467 {
00468 refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
00469 }
00470
00471
00472 clkdiv = 2 * refFreq;
00473 clkdiv += baudrate - 1;
00474 clkdiv /= baudrate;
00475 clkdiv -= 4;
00476 clkdiv *= 64;
00477
00478
00479
00480 clkdiv += 0xc0;
00481 clkdiv &= 0xffffff00;
00482
00483
00484 EFM_ASSERT(clkdiv <= _USART_CLKDIV_MASK);
00485
00486
00487 clkdiv &= _USART_CLKDIV_DIV_MASK;
00488
00489 usart->CLKDIV = clkdiv;
00490 }
00491
00492
00493
00508 void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
00509 {
00510 uint32_t tmp;
00511
00512
00513 EFM_ASSERT(USART_REF_VALID(usart) || (UART_REF_VALID(usart)));
00514
00515
00516 tmp = ~((uint32_t) (enable));
00517 tmp &= _USART_CMD_RXEN_MASK | _USART_CMD_TXEN_MASK;
00518 usart->CMD = tmp << 1;
00519
00520
00521 usart->CMD = (uint32_t) (enable);
00522 }
00523
00524
00525
00548 void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
00549 {
00550
00551 EFM_ASSERT(USART_REF_VALID(usart) || UART_REF_VALID(usart));
00552
00553
00554 USART_Reset(usart);
00555
00556 #if defined(USART_INPUT_RXPRS) && defined(USART_CTRL_MVDIS)
00557
00558 if (init->mvdis)
00559 {
00560 usart->CTRL |= USART_CTRL_MVDIS;
00561 }
00562
00563
00564 if (init->prsRxEnable)
00565 {
00566 usart->INPUT = (uint32_t) init->prsRxCh | USART_INPUT_RXPRS;
00567 }
00568 #endif
00569
00570
00571 usart->FRAME = (uint32_t) (init->databits) |
00572 (uint32_t) (init->stopbits) |
00573 (uint32_t) (init->parity);
00574
00575
00576 USART_BaudrateAsyncSet(usart, init->refFreq, init->baudrate, init->oversampling);
00577
00578
00579 usart->CMD = (uint32_t) (init->enable);
00580 }
00581
00582
00583
00607 void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init)
00608 {
00609
00610 EFM_ASSERT(USART_REF_VALID(usart));
00611
00612
00613 USART_Reset(usart);
00614
00615
00616 usart->CTRL |= (USART_CTRL_SYNC) |
00617 ((uint32_t) init->clockMode) |
00618 (init->msbf ? USART_CTRL_MSBF : 0);
00619
00620 #if defined(USART_INPUT_RXPRS) && defined(USART_TRIGCTRL_AUTOTXTEN)
00621 usart->CTRL |= (init->prsRxEnable ? USART_INPUT_RXPRS : 0) |
00622 (init->autoTx ? USART_CTRL_AUTOTX : 0);
00623 #endif
00624
00625
00626 usart->FRAME = ((uint32_t) (init->databits)) |
00627 (USART_FRAME_STOPBITS_DEFAULT) |
00628 (USART_FRAME_PARITY_DEFAULT);
00629
00630
00631 USART_BaudrateSyncSet(usart, init->refFreq, init->baudrate);
00632
00633
00634 if (init->master)
00635 {
00636 usart->CMD = USART_CMD_MASTEREN;
00637 }
00638
00639 usart->CMD = (uint32_t) (init->enable);
00640 }
00641
00642
00643 #if defined(USART0) || ((USART_COUNT == 1) && defined(USART1))
00644
00670 void USART_InitIrDA(const USART_InitIrDA_TypeDef *init)
00671 {
00672 #if (USART_COUNT == 1) && defined(USART1)
00673 USART_TypeDef *usart = USART1;
00674 #else
00675 USART_TypeDef *usart = USART0;
00676 #endif
00677
00678
00679 USART_InitAsync(usart, &(init->async));
00680
00681
00682 usart->CTRL |= USART_CTRL_TXINV;
00683
00684
00685 if (init->irRxInv)
00686 {
00687 usart->CTRL |= USART_CTRL_RXINV;
00688 }
00689
00690
00691 usart->IRCTRL |= (uint32_t) init->irPw |
00692 (uint32_t) init->irPrsSel |
00693 ((uint32_t) init->irFilt << _USART_IRCTRL_IRFILT_SHIFT) |
00694 ((uint32_t) init->irPrsEn << _USART_IRCTRL_IRPRSEN_SHIFT);
00695
00696
00697 usart->IRCTRL |= USART_IRCTRL_IREN;
00698 }
00699 #endif
00700
00701
00702 #if defined(_USART_I2SCTRL_MASK)
00703
00732 void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init)
00733 {
00734 USART_Enable_TypeDef enable;
00735
00736
00737 EFM_ASSERT(USART_I2S_VALID(usart));
00738
00739
00740 enable = init->sync.enable;
00741 init->sync.enable = usartDisable;
00742
00743
00744 USART_InitSync(usart, &init->sync);
00745
00746
00747 usart->I2SCTRL = ((uint32_t) init->format) |
00748 ((uint32_t) init->justify) |
00749 (init->delay ? USART_I2SCTRL_DELAY : 0) |
00750 (init->dmaSplit ? USART_I2SCTRL_DMASPLIT : 0) |
00751 (init->mono ? USART_I2SCTRL_MONO : 0) |
00752 (USART_I2SCTRL_EN);
00753
00754 if (enable != usartDisable)
00755 {
00756 USART_Enable(usart, enable);
00757 }
00758 }
00759 #endif
00760
00761
00762
00771 void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init)
00772 {
00773 uint32_t trigctrl;
00774
00775
00776 trigctrl = usart->TRIGCTRL & ~(_USART_TRIGCTRL_RXTEN_MASK |
00777 _USART_TRIGCTRL_TXTEN_MASK |
00778 #if defined(USART_TRIGCTRL_AUTOTXTEN)
00779 _USART_TRIGCTRL_AUTOTXTEN_MASK |
00780 #endif
00781 _USART_TRIGCTRL_TSEL_MASK);
00782
00783 #if defined(USART_TRIGCTRL_AUTOTXTEN)
00784 if (init->autoTxTriggerEnable)
00785 {
00786 trigctrl |= USART_TRIGCTRL_AUTOTXTEN;
00787 }
00788 #endif
00789 if (init->txTriggerEnable)
00790 {
00791 trigctrl |= USART_TRIGCTRL_TXTEN;
00792 }
00793 if (init->rxTriggerEnable)
00794 {
00795 trigctrl |= USART_TRIGCTRL_RXTEN;
00796 }
00797 trigctrl |= init->prsTriggerChannel;
00798
00799
00800 usart->TRIGCTRL = trigctrl;
00801 }
00802
00803
00804
00811 void USART_Reset(USART_TypeDef *usart)
00812 {
00813
00814 EFM_ASSERT(USART_REF_VALID(usart) || UART_REF_VALID(usart));
00815
00816
00817 usart->CMD = USART_CMD_RXDIS | USART_CMD_TXDIS | USART_CMD_MASTERDIS |
00818 USART_CMD_RXBLOCKDIS | USART_CMD_TXTRIDIS | USART_CMD_CLEARTX | USART_CMD_CLEARRX;
00819 usart->CTRL = _USART_CTRL_RESETVALUE;
00820 usart->FRAME = _USART_FRAME_RESETVALUE;
00821 usart->TRIGCTRL = _USART_TRIGCTRL_RESETVALUE;
00822 usart->CLKDIV = _USART_CLKDIV_RESETVALUE;
00823 usart->IEN = _USART_IEN_RESETVALUE;
00824 usart->IFC = _USART_IFC_MASK;
00825 usart->ROUTE = _USART_ROUTE_RESETVALUE;
00826
00827 if (USART_IRDA_VALID(usart))
00828 {
00829 usart->IRCTRL = _USART_IRCTRL_RESETVALUE;
00830 }
00831
00832 #if defined(_USART_INPUT_RESETVALUE)
00833 usart->INPUT = _USART_INPUT_RESETVALUE;
00834 #endif
00835
00836 #if defined(_USART_I2SCTRL_RESETVALUE)
00837 if (USART_I2S_VALID(usart))
00838 {
00839 usart->I2SCTRL = _USART_I2SCTRL_RESETVALUE;
00840 }
00841 #endif
00842 }
00843
00844
00845
00869 uint8_t USART_Rx(USART_TypeDef *usart)
00870 {
00871 while (!(usart->STATUS & USART_STATUS_RXDATAV))
00872 ;
00873
00874 return (uint8_t) (usart->RXDATA);
00875 }
00876
00877
00878
00902 uint16_t USART_RxDouble(USART_TypeDef *usart)
00903 {
00904 while (!(usart->STATUS & USART_STATUS_RXFULL))
00905 ;
00906
00907 return (uint16_t) (usart->RXDOUBLE);
00908 }
00909
00910
00911
00935 uint32_t USART_RxDoubleExt(USART_TypeDef *usart)
00936 {
00937 while (!(usart->STATUS & USART_STATUS_RXFULL))
00938 ;
00939
00940 return usart->RXDOUBLEX;
00941 }
00942
00943
00944
00968 uint16_t USART_RxExt(USART_TypeDef *usart)
00969 {
00970 while (!(usart->STATUS & USART_STATUS_RXDATAV))
00971 ;
00972
00973 return (uint16_t) (usart->RXDATAX);
00974 }
00975
00976
00977
00996 uint8_t USART_SpiTransfer(USART_TypeDef *usart, uint8_t data)
00997 {
00998 while (!(usart->STATUS & USART_STATUS_TXBL))
00999 ;
01000 usart->TXDATA = (uint32_t) data;
01001 while (!(usart->STATUS & USART_STATUS_TXC))
01002 ;
01003 return (uint8_t) (usart->RXDATA);
01004 }
01005
01006
01007
01030 void USART_Tx(USART_TypeDef *usart, uint8_t data)
01031 {
01032
01033 while (!(usart->STATUS & USART_STATUS_TXBL))
01034 ;
01035 usart->TXDATA = (uint32_t) data;
01036 }
01037
01038
01039
01066 void USART_TxDouble(USART_TypeDef *usart, uint16_t data)
01067 {
01068
01069 while (!(usart->STATUS & USART_STATUS_TXBL))
01070 ;
01071 usart->TXDOUBLE = (uint32_t) data;
01072 }
01073
01074
01075
01102 void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data)
01103 {
01104
01105 while (!(usart->STATUS & USART_STATUS_TXBL))
01106 ;
01107 usart->TXDOUBLEX = data;
01108 }
01109
01110
01111
01130 void USART_TxExt(USART_TypeDef *usart, uint16_t data)
01131 {
01132
01133 while (!(usart->STATUS & USART_STATUS_TXBL))
01134 ;
01135 usart->TXDATAX = (uint32_t) data;
01136 }
01137
01138
01141 #endif