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) && defined(USART2)
00068 #define USART_REF_VALID(ref) (((ref) == USART1) || ((ref) == USART2))
00069
00070 #elif (USART_COUNT == 2)
00071 #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1))
00072
00073 #elif (USART_COUNT == 3)
00074 #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1) || \
00075 ((ref) == USART2))
00076 #elif (USART_COUNT == 4)
00077 #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1) || \
00078 ((ref) == USART2) || ((ref) == USART3))
00079 #else
00080 #error Undefined number of USARTs.
00081 #endif
00082
00083 #if (USARTRF_COUNT == 1) && defined(USARTRF0)
00084 #define USARTRF_REF_VALID(ref) ((ref) == USARTRF0)
00085 #else
00086 #define USARTRF_REF_VALID(ref) (0)
00087 #endif
00088
00089 #if defined( _EFM32_HAPPY_FAMILY )
00090 #define USART_IRDA_VALID(ref) (((ref) == USART0) || ((ref) == USART1))
00091 #elif defined(USART0)
00092 #define USART_IRDA_VALID(ref) ((ref) == USART0)
00093 #elif (USART_COUNT == 1) && defined(USART1)
00094 #define USART_IRDA_VALID(ref) ((ref) == USART1)
00095 #else
00096 #define USART_IRDA_VALID(ref) (0)
00097 #endif
00098
00099 #if defined( _EFM32_HAPPY_FAMILY )
00100 #define USART_I2S_VALID(ref) (((ref) == USART0) || ((ref) == USART1))
00101 #elif defined(_EFM32_TINY_FAMILY) || defined(_EFM32_ZERO_FAMILY)
00102 #define USART_I2S_VALID(ref) ((ref) == USART1)
00103 #elif defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00104 #define USART_I2S_VALID(ref) (((ref) == USART1) || ((ref) == USART2))
00105 #endif
00106
00107 #if (UART_COUNT == 1)
00108 #define UART_REF_VALID(ref) ((ref) == UART0)
00109 #elif (UART_COUNT == 2)
00110 #define UART_REF_VALID(ref) (((ref) == UART0) || ((ref) == UART1))
00111 #else
00112 #define UART_REF_VALID(ref) (0)
00113 #endif
00114
00118
00119
00120
00121
00122
00144 void USART_BaudrateAsyncSet(USART_TypeDef *usart,
00145 uint32_t refFreq,
00146 uint32_t baudrate,
00147 USART_OVS_TypeDef ovs)
00148 {
00149 uint32_t clkdiv;
00150 uint32_t oversample;
00151
00152
00153 EFM_ASSERT(baudrate);
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 if (!refFreq)
00183 {
00184 refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
00185 }
00186
00187
00188 switch (ovs)
00189 {
00190 case USART_CTRL_OVS_X16:
00191 EFM_ASSERT(baudrate <= (refFreq / 16));
00192 oversample = 16;
00193 break;
00194
00195 case USART_CTRL_OVS_X8:
00196 EFM_ASSERT(baudrate <= (refFreq / 8));
00197 oversample = 8;
00198 break;
00199
00200 case USART_CTRL_OVS_X6:
00201 EFM_ASSERT(baudrate <= (refFreq / 6));
00202 oversample = 6;
00203 break;
00204
00205 case USART_CTRL_OVS_X4:
00206 EFM_ASSERT(baudrate <= (refFreq / 4));
00207 oversample = 4;
00208 break;
00209
00210 default:
00211
00212 EFM_ASSERT(0);
00213 return;
00214 }
00215
00216
00217
00218
00219
00220
00221 clkdiv = 4 * refFreq + (oversample * baudrate) / 2;
00222 clkdiv /= (oversample * baudrate);
00223 clkdiv -= 4;
00224 clkdiv *= 64;
00225
00226
00227 EFM_ASSERT(clkdiv <= _USART_CLKDIV_MASK);
00228
00229
00230 clkdiv &= _USART_CLKDIV_MASK;
00231
00232 usart->CTRL &= ~_USART_CTRL_OVS_MASK;
00233 usart->CTRL |= ovs;
00234 usart->CLKDIV = clkdiv;
00235 }
00236
00237
00238
00266 uint32_t USART_BaudrateCalc(uint32_t refFreq,
00267 uint32_t clkdiv,
00268 bool syncmode,
00269 USART_OVS_TypeDef ovs)
00270 {
00271 uint32_t oversample;
00272 uint32_t divisor;
00273 uint32_t factor;
00274 uint32_t remainder;
00275 uint32_t quotient;
00276 uint32_t br;
00277
00278
00279 clkdiv &= _USART_CLKDIV_MASK;
00280
00281
00282
00283
00284
00285 if (syncmode)
00286 {
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 oversample = 1;
00297 factor = 128;
00298 }
00299 else
00300 {
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 switch (ovs)
00315 {
00316 case USART_CTRL_OVS_X16:
00317 oversample = 1;
00318 factor = 256 / 16;
00319 break;
00320
00321 case USART_CTRL_OVS_X8:
00322 oversample = 1;
00323 factor = 256 / 8;
00324 break;
00325
00326 case USART_CTRL_OVS_X6:
00327 oversample = 3;
00328 factor = 256 / 2;
00329 break;
00330
00331 default:
00332 oversample = 1;
00333 factor = 256 / 4;
00334 break;
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 divisor = oversample * (256 + clkdiv);
00362
00363 quotient = refFreq / divisor;
00364 remainder = refFreq % divisor;
00365
00366
00367
00368 br = factor * quotient;
00369
00370
00371
00372
00373
00374
00375 br += (factor * remainder) / divisor;
00376
00377 return br;
00378 }
00379
00380
00381
00395 uint32_t USART_BaudrateGet(USART_TypeDef *usart)
00396 {
00397 uint32_t freq;
00398 USART_OVS_TypeDef ovs;
00399 bool syncmode;
00400
00401 if (usart->CTRL & USART_CTRL_SYNC)
00402 {
00403 syncmode = true;
00404 }
00405 else
00406 {
00407 syncmode = false;
00408 }
00409
00410
00411 freq = CMU_ClockFreqGet(cmuClock_HFPER);
00412 ovs = (USART_OVS_TypeDef) (usart->CTRL & _USART_CTRL_OVS_MASK);
00413 return USART_BaudrateCalc(freq, usart->CLKDIV, syncmode, ovs);
00414 }
00415
00416
00417
00444 void USART_BaudrateSyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate)
00445 {
00446 uint32_t clkdiv;
00447
00448
00449 EFM_ASSERT(baudrate);
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 if (!refFreq)
00479 {
00480 refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
00481 }
00482
00483
00484 clkdiv = 2 * refFreq;
00485 clkdiv += baudrate - 1;
00486 clkdiv /= baudrate;
00487 clkdiv -= 4;
00488 clkdiv *= 64;
00489
00490
00491
00492 clkdiv += 0xc0;
00493 clkdiv &= 0xffffff00;
00494
00495
00496 EFM_ASSERT(clkdiv <= _USART_CLKDIV_MASK);
00497
00498
00499 clkdiv &= _USART_CLKDIV_DIV_MASK;
00500
00501 usart->CLKDIV = clkdiv;
00502 }
00503
00504
00505
00520 void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
00521 {
00522 uint32_t tmp;
00523
00524
00525 EFM_ASSERT( USART_REF_VALID(usart)
00526 || USARTRF_REF_VALID(usart)
00527 || UART_REF_VALID(usart) );
00528
00529
00530 tmp = ~((uint32_t) (enable));
00531 tmp &= _USART_CMD_RXEN_MASK | _USART_CMD_TXEN_MASK;
00532 usart->CMD = tmp << 1;
00533
00534
00535 usart->CMD = (uint32_t) (enable);
00536 }
00537
00538
00539
00562 void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
00563 {
00564
00565 EFM_ASSERT( USART_REF_VALID(usart)
00566 || USARTRF_REF_VALID(usart)
00567 || UART_REF_VALID(usart) );
00568
00569
00570 USART_Reset(usart);
00571
00572 #if defined(USART_INPUT_RXPRS) && defined(USART_CTRL_MVDIS)
00573
00574 if (init->mvdis)
00575 {
00576 usart->CTRL |= USART_CTRL_MVDIS;
00577 }
00578
00579
00580 if (init->prsRxEnable)
00581 {
00582 usart->INPUT = (uint32_t) init->prsRxCh | USART_INPUT_RXPRS;
00583 }
00584 #endif
00585
00586
00587 usart->FRAME = (uint32_t) (init->databits) |
00588 (uint32_t) (init->stopbits) |
00589 (uint32_t) (init->parity);
00590
00591
00592 USART_BaudrateAsyncSet(usart, init->refFreq, init->baudrate, init->oversampling);
00593
00594
00595 usart->CMD = (uint32_t) (init->enable);
00596 }
00597
00598
00599
00623 void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init)
00624 {
00625
00626 EFM_ASSERT( USART_REF_VALID(usart) || USARTRF_REF_VALID(usart) );
00627
00628
00629 USART_Reset(usart);
00630
00631
00632 usart->CTRL |= (USART_CTRL_SYNC) |
00633 ((uint32_t) init->clockMode) |
00634 (init->msbf ? USART_CTRL_MSBF : 0);
00635
00636 #if defined(USART_INPUT_RXPRS) && defined(USART_TRIGCTRL_AUTOTXTEN)
00637 usart->CTRL |= (init->prsRxEnable ? USART_INPUT_RXPRS : 0) |
00638 (init->autoTx ? USART_CTRL_AUTOTX : 0);
00639 #endif
00640
00641
00642 usart->FRAME = ((uint32_t) (init->databits)) |
00643 (USART_FRAME_STOPBITS_DEFAULT) |
00644 (USART_FRAME_PARITY_DEFAULT);
00645
00646
00647 USART_BaudrateSyncSet(usart, init->refFreq, init->baudrate);
00648
00649
00650 if (init->master)
00651 {
00652 usart->CMD = USART_CMD_MASTEREN;
00653 }
00654
00655 usart->CMD = (uint32_t) (init->enable);
00656 }
00657
00658
00659 #if defined(USART0) || ((USART_COUNT == 1) && defined(USART1))
00660
00686 void USART_InitIrDA(const USART_InitIrDA_TypeDef *init)
00687 {
00688 #if (USART_COUNT == 1) && defined(USART1)
00689 USART_TypeDef *usart = USART1;
00690 #else
00691 USART_TypeDef *usart = USART0;
00692 #endif
00693
00694
00695 USART_InitAsync(usart, &(init->async));
00696
00697
00698 usart->CTRL |= USART_CTRL_TXINV;
00699
00700
00701 if (init->irRxInv)
00702 {
00703 usart->CTRL |= USART_CTRL_RXINV;
00704 }
00705
00706
00707 usart->IRCTRL |= (uint32_t) init->irPw |
00708 (uint32_t) init->irPrsSel |
00709 ((uint32_t) init->irFilt << _USART_IRCTRL_IRFILT_SHIFT) |
00710 ((uint32_t) init->irPrsEn << _USART_IRCTRL_IRPRSEN_SHIFT);
00711
00712
00713 usart->IRCTRL |= USART_IRCTRL_IREN;
00714 }
00715 #endif
00716
00717
00718 #if defined(_USART_I2SCTRL_MASK)
00719
00748 void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init)
00749 {
00750 USART_Enable_TypeDef enable;
00751
00752
00753 EFM_ASSERT(USART_I2S_VALID(usart));
00754
00755
00756 enable = init->sync.enable;
00757 init->sync.enable = usartDisable;
00758
00759
00760 USART_InitSync(usart, &init->sync);
00761
00762
00763 usart->I2SCTRL = ((uint32_t) init->format) |
00764 ((uint32_t) init->justify) |
00765 (init->delay ? USART_I2SCTRL_DELAY : 0) |
00766 (init->dmaSplit ? USART_I2SCTRL_DMASPLIT : 0) |
00767 (init->mono ? USART_I2SCTRL_MONO : 0) |
00768 (USART_I2SCTRL_EN);
00769
00770 if (enable != usartDisable)
00771 {
00772 USART_Enable(usart, enable);
00773 }
00774 }
00775 #endif
00776
00777
00778
00787 void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init)
00788 {
00789 uint32_t trigctrl;
00790
00791
00792 trigctrl = usart->TRIGCTRL & ~(_USART_TRIGCTRL_RXTEN_MASK |
00793 _USART_TRIGCTRL_TXTEN_MASK |
00794 #if defined(USART_TRIGCTRL_AUTOTXTEN)
00795 _USART_TRIGCTRL_AUTOTXTEN_MASK |
00796 #endif
00797 _USART_TRIGCTRL_TSEL_MASK);
00798
00799 #if defined(USART_TRIGCTRL_AUTOTXTEN)
00800 if (init->autoTxTriggerEnable)
00801 {
00802 trigctrl |= USART_TRIGCTRL_AUTOTXTEN;
00803 }
00804 #endif
00805 if (init->txTriggerEnable)
00806 {
00807 trigctrl |= USART_TRIGCTRL_TXTEN;
00808 }
00809 if (init->rxTriggerEnable)
00810 {
00811 trigctrl |= USART_TRIGCTRL_RXTEN;
00812 }
00813 trigctrl |= init->prsTriggerChannel;
00814
00815
00816 usart->TRIGCTRL = trigctrl;
00817 }
00818
00819
00820
00827 void USART_Reset(USART_TypeDef *usart)
00828 {
00829
00830 EFM_ASSERT( USART_REF_VALID(usart)
00831 || USARTRF_REF_VALID(usart)
00832 || UART_REF_VALID(usart) );
00833
00834
00835 usart->CMD = USART_CMD_RXDIS | USART_CMD_TXDIS | USART_CMD_MASTERDIS |
00836 USART_CMD_RXBLOCKDIS | USART_CMD_TXTRIDIS | USART_CMD_CLEARTX | USART_CMD_CLEARRX;
00837 usart->CTRL = _USART_CTRL_RESETVALUE;
00838 usart->FRAME = _USART_FRAME_RESETVALUE;
00839 usart->TRIGCTRL = _USART_TRIGCTRL_RESETVALUE;
00840 usart->CLKDIV = _USART_CLKDIV_RESETVALUE;
00841 usart->IEN = _USART_IEN_RESETVALUE;
00842 usart->IFC = _USART_IFC_MASK;
00843 usart->ROUTE = _USART_ROUTE_RESETVALUE;
00844
00845 if (USART_IRDA_VALID(usart))
00846 {
00847 usart->IRCTRL = _USART_IRCTRL_RESETVALUE;
00848 }
00849
00850 #if defined(_USART_INPUT_RESETVALUE)
00851 usart->INPUT = _USART_INPUT_RESETVALUE;
00852 #endif
00853
00854 #if defined(_USART_I2SCTRL_RESETVALUE)
00855 if (USART_I2S_VALID(usart))
00856 {
00857 usart->I2SCTRL = _USART_I2SCTRL_RESETVALUE;
00858 }
00859 #endif
00860 }
00861
00862
00863
00887 uint8_t USART_Rx(USART_TypeDef *usart)
00888 {
00889 while (!(usart->STATUS & USART_STATUS_RXDATAV))
00890 ;
00891
00892 return (uint8_t) (usart->RXDATA);
00893 }
00894
00895
00896
00920 uint16_t USART_RxDouble(USART_TypeDef *usart)
00921 {
00922 while (!(usart->STATUS & USART_STATUS_RXFULL))
00923 ;
00924
00925 return (uint16_t) (usart->RXDOUBLE);
00926 }
00927
00928
00929
00953 uint32_t USART_RxDoubleExt(USART_TypeDef *usart)
00954 {
00955 while (!(usart->STATUS & USART_STATUS_RXFULL))
00956 ;
00957
00958 return usart->RXDOUBLEX;
00959 }
00960
00961
00962
00986 uint16_t USART_RxExt(USART_TypeDef *usart)
00987 {
00988 while (!(usart->STATUS & USART_STATUS_RXDATAV))
00989 ;
00990
00991 return (uint16_t) (usart->RXDATAX);
00992 }
00993
00994
00995
01014 uint8_t USART_SpiTransfer(USART_TypeDef *usart, uint8_t data)
01015 {
01016 while (!(usart->STATUS & USART_STATUS_TXBL))
01017 ;
01018 usart->TXDATA = (uint32_t) data;
01019 while (!(usart->STATUS & USART_STATUS_TXC))
01020 ;
01021 return (uint8_t) (usart->RXDATA);
01022 }
01023
01024
01025
01048 void USART_Tx(USART_TypeDef *usart, uint8_t data)
01049 {
01050
01051 while (!(usart->STATUS & USART_STATUS_TXBL))
01052 ;
01053 usart->TXDATA = (uint32_t) data;
01054 }
01055
01056
01057
01084 void USART_TxDouble(USART_TypeDef *usart, uint16_t data)
01085 {
01086
01087 while (!(usart->STATUS & USART_STATUS_TXBL))
01088 ;
01089 usart->TXDOUBLE = (uint32_t) data;
01090 }
01091
01092
01093
01120 void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data)
01121 {
01122
01123 while (!(usart->STATUS & USART_STATUS_TXBL))
01124 ;
01125 usart->TXDOUBLEX = data;
01126 }
01127
01128
01129
01148 void USART_TxExt(USART_TypeDef *usart, uint16_t data)
01149 {
01150
01151 while (!(usart->STATUS & USART_STATUS_TXBL))
01152 ;
01153 usart->TXDATAX = (uint32_t) data;
01154 }
01155
01156
01159 #endif