1 /***************************************************************************//**
2  * @file
3  * @brief Universal synchronous/asynchronous receiver/transmitter (USART/UART)
4  *   Peripheral API
5  * @author Energy Micro AS
6  * @version 3.0.0
7  *******************************************************************************
8  * @section License
9  * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
10  *******************************************************************************
11  *
12  * Permission is granted to anyone to use this software for any purpose,
13  * including commercial applications, and to alter it and redistribute it
14  * freely, subject to the following restrictions:
15  *
16  * 1. The origin of this software must not be misrepresented; you must not
17  *    claim that you wrote the original software.
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 3. This notice may not be removed or altered from any source distribution.
21  *
22  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
23  * obligation to support this Software. Energy Micro AS is providing the
24  * Software "AS IS", with no express or implied warranties of any kind,
25  * including, but not limited to, any implied warranties of merchantability
26  * or fitness for any particular purpose or warranties against infringement
27  * of any proprietary rights of a third party.
28  *
29  * Energy Micro AS will not be liable for any consequential, incidental, or
30  * special damages, or any other relief, or for any claim by any third party,
31  * arising from your use of this Software.
32  *
33  ******************************************************************************/
34 #include "em_usart.h"
35 #include "em_cmu.h"
36 #include "em_assert.h"
37 
38 /***************************************************************************//**
39  * @addtogroup EM_Library
40  * @{
41  ******************************************************************************/
42 
43 /***************************************************************************//**
44  * @addtogroup USART
45  * @brief Universal Synchronous/Asynchronous Receiver/Transmitter
46  *   Peripheral API
47  * @{
48  ******************************************************************************/
49 
50 /*******************************************************************************
51  *******************************   DEFINES   ***********************************
52  ******************************************************************************/
53 
54 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
55 
56 
57 /** Validation of USART register block pointer reference for assert statements. */
58 #if (USART_COUNT == 1)
59 #define USART_REF_VALID(ref)    ((ref) == USART0)
60 
61 #elif (USART_COUNT == 2)
62 #define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1))
63 
64 #elif (USART_COUNT == 3)
65 #define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
66                                  ((ref) == USART2))
67 #elif (USART_COUNT == 4)
68 #define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
69                                  ((ref) == USART2) || ((ref) == USART3))
70 #else
71 #error Undefined number of USARTs.
72 #endif
73 
74 #define USART_IRDA_VALID(ref)    ((ref) == USART0)
75 
76 #if defined(_EFM32_TINY_FAMILY)
77 #define USART_I2S_VALID(ref)     ((ref) == USART1)
78 #endif
79 
80 #if defined(_EFM32_GIANT_FAMILY)
81 #define USART_I2S_VALID(ref)    (((ref) == USART1) || ((ref) == USART2))
82 #endif
83 
84 #if (UART_COUNT == 1)
85 #define UART_REF_VALID(ref)     ((ref)==UART0)
86 #elif (UART_COUNT == 2)
87 #define UART_REF_VALID(ref)     (((ref)==UART0) || ((ref)==UART1))
88 #else
89 #define UART_REF_VALID(ref)     (0)
90 #endif
91 
92 /** @endcond */
93 
94 
95 /*******************************************************************************
96  **************************   GLOBAL FUNCTIONS   *******************************
97  ******************************************************************************/
98 
99 /***************************************************************************//**
100  * @brief
101  *   Configure USART/UART operating in asynchronous mode to use a given
102  *   baudrate (or as close as possible to specified baudrate).
103  *
104  * @param[in] usart
105  *   Pointer to USART/UART peripheral register block.
106  *
107  * @param[in] refFreq
108  *   USART/UART reference clock frequency in Hz that will be used. If set to 0,
109  *   the currently configured reference clock is assumed.
110  *
111  * @param[in] baudrate
112  *   Baudrate to try to achieve for USART/UART.
113  *
114  * @param[in] ovs
115  *   Oversampling to be used. Normal is 16x oversampling, but lower oversampling
116  *   may be used to achieve higher rates or better baudrate accuracy in some
117  *   cases. Notice that lower oversampling frequency makes channel more
118  *   vulnerable to bit faults during reception due to clock inaccuracies
119  *   compared to link partner.
120  ******************************************************************************/
USART_BaudrateAsyncSet(USART_TypeDef * usart,uint32_t refFreq,uint32_t baudrate,USART_OVS_TypeDef ovs)121 void USART_BaudrateAsyncSet(USART_TypeDef *usart,
122                             uint32_t refFreq,
123                             uint32_t baudrate,
124                             USART_OVS_TypeDef ovs)
125 {
126   uint32_t clkdiv;
127   uint32_t oversample;
128 
129   /* Inhibit divide by 0 */
130   EFM_ASSERT(baudrate);
131 
132   /*
133    * We want to use integer division to avoid forcing in float division
134    * utils, and yet keep rounding effect errors to a minimum.
135    *
136    * CLKDIV in asynchronous mode is given by:
137    *
138    * CLKDIV = 256 * (fHFPERCLK/(oversample * br) - 1)
139    * or
140    * CLKDIV = (256 * fHFPERCLK)/(oversample * br) - 256
141    *
142    * The basic problem with integer division in the above formula is that
143    * the dividend (256 * fHFPERCLK) may become higher than max 32 bit
144    * integer. Yet, we want to evaluate dividend first before dividing in
145    * order to get as small rounding effects as possible. We do not want
146    * to make too harsh restrictions on max fHFPERCLK value either.
147    *
148    * One can possibly factorize 256 and oversample/br. However,
149    * since the last 6 bits of CLKDIV are don't care, we can base our
150    * integer arithmetic on the below formula
151    *
152    * CLKDIV / 64 = (4 * fHFPERCLK)/(oversample * br) - 4
153    *
154    * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
155    * up to 1GHz without overflowing a 32 bit value!
156    */
157 
158   /* HFPERCLK used to clock all USART/UART peripheral modules */
159   if (!refFreq)
160   {
161     refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
162   }
163 
164   /* Map oversampling */
165   switch (ovs)
166   {
167   case USART_CTRL_OVS_X16:
168     EFM_ASSERT(baudrate <= (refFreq / 16));
169     oversample = 16;
170     break;
171 
172   case USART_CTRL_OVS_X8:
173     EFM_ASSERT(baudrate <= (refFreq / 8));
174     oversample = 8;
175     break;
176 
177   case USART_CTRL_OVS_X6:
178     EFM_ASSERT(baudrate <= (refFreq / 6));
179     oversample = 6;
180     break;
181 
182   case USART_CTRL_OVS_X4:
183     EFM_ASSERT(baudrate <= (refFreq / 4));
184     oversample = 4;
185     break;
186 
187   default:
188     /* Invalid input */
189     EFM_ASSERT(0);
190     return;
191   }
192 
193   /* Calculate and set CLKDIV with fractional bits */
194   clkdiv  = 4 * refFreq + (oversample * baudrate) / 2;
195   clkdiv /= (oversample * baudrate);
196   clkdiv -= 4;
197   clkdiv *= 64;
198 
199   usart->CTRL  &= ~_USART_CTRL_OVS_MASK;
200   usart->CTRL  |= ovs;
201   usart->CLKDIV = clkdiv;
202 }
203 
204 
205 /***************************************************************************//**
206  * @brief
207  *   Calculate baudrate for USART/UART given reference frequency, clock division
208  *   and oversampling rate (if async mode).
209  *
210  * @details
211  *   This function returns the baudrate that a USART/UART module will use if
212  *   configured with the given frequency, clock divisor and mode. Notice that
213  *   this function will not use actual HW configuration. It can be used
214  *   to determinate if a given configuration is sufficiently accurate for the
215  *   application.
216  *
217  * @param[in] refFreq
218  *   USART/UART HF peripheral frequency used.
219  *
220  * @param[in] clkdiv
221  *   Clock division factor to be used.
222  *
223  * @param[in] syncmode
224  *   @li true - synchronous mode operation.
225  *   @li false - asynchronous mode operation.
226  *
227  * @param[in] ovs
228  *   Oversampling used if asynchronous mode. Not used if @p syncmode is true.
229  *
230  * @return
231  *   Baudrate with given settings.
232  ******************************************************************************/
USART_BaudrateCalc(uint32_t refFreq,uint32_t clkdiv,bool syncmode,USART_OVS_TypeDef ovs)233 uint32_t USART_BaudrateCalc(uint32_t refFreq,
234                             uint32_t clkdiv,
235                             bool syncmode,
236                             USART_OVS_TypeDef ovs)
237 {
238   uint32_t oversample;
239   uint32_t divisor;
240   uint32_t factor;
241   uint32_t remainder;
242   uint32_t quotient;
243   uint32_t br;
244 
245   /* Mask out unused bits */
246   clkdiv &= _USART_CLKDIV_MASK;
247 
248   /* We want to use integer division to avoid forcing in float division */
249   /* utils, and yet keep rounding effect errors to a minimum. */
250 
251   /* Baudrate calculation depends on if synchronous or asynchronous mode */
252   if (syncmode)
253   {
254     /*
255      * Baudrate is given by:
256      *
257      * br = fHFPERCLK/(2 * (1 + (CLKDIV / 256)))
258      *
259      * which can be rewritten to
260      *
261      * br = (128 * fHFPERCLK)/(256 + CLKDIV)
262      */
263     oversample = 1; /* Not used in sync mode, ie 1 */
264     factor     = 128;
265   }
266   else
267   {
268     /*
269      * Baudrate in asynchronous mode is given by:
270      *
271      * br = fHFPERCLK/(oversample * (1 + (CLKDIV / 256)))
272      *
273      * which can be rewritten to
274      *
275      * br = (256 * fHFPERCLK)/(oversample * (256 + CLKDIV))
276      *
277      * First of all we can reduce the 256 factor of the dividend with
278      * (part of) oversample part of the divisor.
279      */
280 
281     switch (ovs)
282     {
283     case USART_CTRL_OVS_X16:
284       oversample = 1;
285       factor     = 256 / 16;
286       break;
287 
288     case USART_CTRL_OVS_X8:
289       oversample = 1;
290       factor     = 256 / 8;
291       break;
292 
293     case USART_CTRL_OVS_X6:
294       oversample = 3;
295       factor     = 256 / 2;
296       break;
297 
298     default:
299       oversample = 1;
300       factor     = 256 / 4;
301       break;
302     }
303   }
304 
305   /*
306    * The basic problem with integer division in the above formula is that
307    * the dividend (factor * fHFPERCLK) may become higher than max 32 bit
308    * integer. Yet we want to evaluate dividend first before dividing in
309    * order to get as small rounding effects as possible. We do not want
310    * to make too harsh restrictions on max fHFPERCLK value either.
311    *
312    * For division a/b, we can write
313    *
314    * a = qb + r
315    *
316    * where q is the quotient and r is the remainder, both integers.
317    *
318    * The orignal baudrate formula can be rewritten as
319    *
320    * br = xa / b = x(qb + r)/b = xq + xr/b
321    *
322    * where x is 'factor', a is 'refFreq' and b is 'divisor', referring to
323    * variable names.
324    */
325 
326   /* Divisor will never exceed max 32 bit value since clkdiv <= 0x1fffc0 */
327   /* and 'oversample' has been reduced to <= 3. */
328   divisor = oversample * (256 + clkdiv);
329 
330   quotient  = refFreq / divisor;
331   remainder = refFreq % divisor;
332 
333   /* factor <= 128 and since divisor >= 256, the below cannot exceed max */
334   /* 32 bit value. */
335   br = factor * quotient;
336 
337   /*
338    * factor <= 128 and remainder < (oversample*(256 + clkdiv)), which
339    * means dividend (factor * remainder) worst case is
340    * 128*(3 * (256 + 0x1fffc0)) = 0x30012000.
341    */
342   br += (factor * remainder) / divisor;
343 
344   return br;
345 }
346 
347 
348 /***************************************************************************//**
349  * @brief
350  *   Get current baudrate for USART/UART.
351  *
352  * @details
353  *   This function returns the actual baudrate (not considering oscillator
354  *   inaccuracies) used by a USART/UART peripheral.
355  *
356  * @param[in] usart
357  *   Pointer to USART/UART peripheral register block.
358  *
359  * @return
360  *   Current baudrate.
361  ******************************************************************************/
USART_BaudrateGet(USART_TypeDef * usart)362 uint32_t USART_BaudrateGet(USART_TypeDef *usart)
363 {
364   uint32_t          freq;
365   USART_OVS_TypeDef ovs;
366   bool              syncmode;
367 
368   if (usart->CTRL & USART_CTRL_SYNC)
369   {
370     syncmode = true;
371   }
372   else
373   {
374     syncmode = false;
375   }
376 
377   /* HFPERCLK used to clock all USART/UART peripheral modules */
378   freq = CMU_ClockFreqGet(cmuClock_HFPER);
379   ovs  = (USART_OVS_TypeDef)(usart->CTRL & _USART_CTRL_OVS_MASK);
380   return USART_BaudrateCalc(freq, usart->CLKDIV, syncmode, ovs);
381 }
382 
383 
384 /***************************************************************************//**
385  * @brief
386  *   Configure USART operating in synchronous mode to use a given baudrate
387  *   (or as close as possible to specified baudrate).
388  *
389  * @details
390  *   The configuration will be set to use a baudrate <= the specified baudrate
391  *   in order to ensure that the baudrate does not exceed the specified value.
392  *
393  *   Fractional clock division is suppressed, although the HW design allows it.
394  *   It could cause half clock cycles to exceed specified limit, and thus
395  *   potentially violate specifications for the slave device. In some special
396  *   situations fractional clock division may be useful even in synchronous
397  *   mode, but in those cases it must be directly adjusted, possibly assisted
398  *   by USART_BaudrateCalc():
399  *
400  * @param[in] usart
401  *   Pointer to USART peripheral register block. (Cannot be used on UART
402  *   modules.)
403  *
404  * @param[in] refFreq
405  *   USART reference clock frequency in Hz that will be used. If set to 0,
406  *   the currently configured reference clock is assumed.
407  *
408  * @param[in] baudrate
409  *   Baudrate to try to achieve for USART.
410  ******************************************************************************/
USART_BaudrateSyncSet(USART_TypeDef * usart,uint32_t refFreq,uint32_t baudrate)411 void USART_BaudrateSyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate)
412 {
413   uint32_t clkdiv;
414 
415   /* Inhibit divide by 0 */
416   EFM_ASSERT(baudrate);
417 
418   /*
419    * We want to use integer division to avoid forcing in float division
420    * utils, and yet keep rounding effect errors to a minimum.
421    *
422    * CLKDIV in synchronous mode is given by:
423    *
424    * CLKDIV = 256 * (fHFPERCLK/(2 * br) - 1)
425    * or
426    * CLKDIV = (256 * fHFPERCLK)/(2 * br) - 256 = (128 * fHFPERCLK)/br - 256
427    *
428    * The basic problem with integer division in the above formula is that
429    * the dividend (128 * fHFPERCLK) may become higher than max 32 bit
430    * integer. Yet, we want to evaluate dividend first before dividing in
431    * order to get as small rounding effects as possible. We do not want
432    * to make too harsh restrictions on max fHFPERCLK value either.
433    *
434    * One can possibly factorize 128 and br. However, since the last
435    * 6 bits of CLKDIV are don't care, we can base our integer arithmetic
436    * on the below formula without loosing any extra precision:
437    *
438    * CLKDIV / 64 = (2 * fHFPERCLK)/br - 4
439    *
440    * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
441    * up to 2GHz without overflowing a 32 bit value!
442    */
443 
444   /* HFPERCLK used to clock all USART/UART peripheral modules */
445   if (!refFreq)
446   {
447     refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
448   }
449 
450   /* Calculate and set CLKDIV with fractional bits */
451   clkdiv  = 2 * refFreq;
452   clkdiv += baudrate - 1;
453   clkdiv /= baudrate;
454   clkdiv -= 4;
455   clkdiv *= 64;
456   /* Make sure we don't use fractional bits by rounding CLKDIV */
457   /* up (and thus reducing baudrate, not increasing baudrate above */
458   /* specified value). */
459   clkdiv       += 0xc0;
460   clkdiv       &= 0xffffff00;
461 
462   /* Verify that resulting clock divider is within limits */
463   EFM_ASSERT(clkdiv <= _USART_CLKDIV_MASK);
464 
465   /* If EFM_ASSERT is not enabled, make sure we don't write to reserved bits */
466   clkdiv       &= _USART_CLKDIV_DIV_MASK;
467 
468   usart->CLKDIV = clkdiv;
469 }
470 
471 
472 /***************************************************************************//**
473  * @brief
474  *   Enable/disable USART/UART receiver and/or transmitter.
475  *
476  * @details
477  *   Notice that this function does not do any configuration. Enabling should
478  *   normally be done after initialization is done (if not enabled as part
479  *   of init).
480  *
481  * @param[in] usart
482  *   Pointer to USART/UART peripheral register block.
483  *
484  * @param[in] enable
485  *   Select status for receiver/transmitter.
486  ******************************************************************************/
USART_Enable(USART_TypeDef * usart,USART_Enable_TypeDef enable)487 void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
488 {
489   uint32_t tmp;
490 
491   /* Make sure the module exists on the selected chip */
492   EFM_ASSERT(USART_REF_VALID(usart)||(UART_REF_VALID(usart)));
493 
494   /* Disable as specified */
495   tmp        = ~((uint32_t)(enable));
496   tmp       &= _USART_CMD_RXEN_MASK | _USART_CMD_TXEN_MASK;
497   usart->CMD = tmp << 1;
498 
499   /* Enable as specified */
500   usart->CMD = (uint32_t)(enable);
501 }
502 
503 
504 /***************************************************************************//**
505  * @brief
506  *   Init USART/UART for normal asynchronous mode.
507  *
508  * @details
509  *   This function will configure basic settings in order to operate in normal
510  *   asynchronous mode.
511  *
512  *   Special control setup not covered by this function must be done after
513  *   using this function by direct modification of the CTRL register.
514  *
515  *   Notice that pins used by the USART/UART module must be properly configured
516  *   by the user explicitly, in order for the USART/UART to work as intended.
517  *   (When configuring pins, one should remember to consider the sequence of
518  *   configuration, in order to avoid unintended pulses/glitches on output
519  *   pins.)
520  *
521  * @param[in] usart
522  *   Pointer to USART/UART peripheral register block.
523  *
524  * @param[in] init
525  *   Pointer to initialization structure used to configure basic async setup.
526  ******************************************************************************/
USART_InitAsync(USART_TypeDef * usart,const USART_InitAsync_TypeDef * init)527 void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
528 {
529   /* Make sure the module exists on the selected chip */
530   EFM_ASSERT(USART_REF_VALID(usart)||UART_REF_VALID(usart));
531 
532   /* Init USART registers to HW reset state. */
533   USART_Reset(usart);
534 
535 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
536   /* Disable majority vote if specified. */
537   if (init->mvdis)
538   {
539     usart->CTRL |= USART_CTRL_MVDIS;
540   }
541 
542   /* Configure PRS input mode. */
543   if (init->prsRxEnable)
544   {
545     usart->INPUT = (uint32_t)init->prsRxCh | USART_INPUT_RXPRS;
546   }
547 #endif
548 
549   /* Configure databits, stopbits and parity */
550   usart->FRAME = (uint32_t)(init->databits) |
551                  (uint32_t)(init->stopbits) |
552                  (uint32_t)(init->parity);
553 
554   /* Configure baudrate */
555   USART_BaudrateAsyncSet(usart, init->refFreq, init->baudrate, init->oversampling);
556 
557   /* Finally enable (as specified) */
558   usart->CMD = (uint32_t)(init->enable);
559 }
560 
561 
562 /***************************************************************************//**
563  * @brief
564  *   Init USART for synchronous mode.
565  *
566  * @details
567  *   This function will configure basic settings in order to operate in
568  *   synchronous mode.
569  *
570  *   Special control setup not covered by this function must be done after
571  *   using this function by direct modification of the CTRL register.
572  *
573  *   Notice that pins used by the USART module must be properly configured
574  *   by the user explicitly, in order for the USART to work as intended.
575  *   (When configuring pins, one should remember to consider the sequence of
576  *   configuration, in order to avoid unintended pulses/glitches on output
577  *   pins.)
578  *
579  * @param[in] usart
580  *   Pointer to USART peripheral register block. (UART does not support this
581  *   mode.)
582  *
583  * @param[in] init
584  *   Pointer to initialization structure used to configure basic async setup.
585  ******************************************************************************/
USART_InitSync(USART_TypeDef * usart,const USART_InitSync_TypeDef * init)586 void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init)
587 {
588   /* Make sure the module exists on the selected chip */
589   EFM_ASSERT(USART_REF_VALID(usart));
590 
591   /* Init USART registers to HW reset state. */
592   USART_Reset(usart);
593 
594   /* Set bits for synchronous mode */
595   usart->CTRL |= (USART_CTRL_SYNC) |
596                  ((uint32_t)init->clockMode) |
597                  (init->msbf ? USART_CTRL_MSBF : 0);
598 
599 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
600   usart->CTRL |= (init->prsRxEnable ? USART_INPUT_RXPRS : 0) |
601                  (init->autoTx      ? USART_CTRL_AUTOTX : 0);
602 #endif
603 
604   /* Configure databits, leave stopbits and parity at reset default (not used) */
605   usart->FRAME = ((uint32_t)(init->databits)) |
606                  (USART_FRAME_STOPBITS_DEFAULT) |
607                  (USART_FRAME_PARITY_DEFAULT);
608 
609   /* Configure baudrate */
610   USART_BaudrateSyncSet(usart, init->refFreq, init->baudrate);
611 
612   /* Finally enable (as specified) */
613   if (init->master)
614   {
615     usart->CMD = USART_CMD_MASTEREN;
616   }
617 
618   usart->CMD = (uint32_t)(init->enable);
619 }
620 
621 
622 /***************************************************************************//**
623  * @brief
624  *   Init USART0 for asynchronous IrDA mode.
625  *
626  * @details
627  *   This function will configure basic settings in order to operate in
628  *   asynchronous IrDA mode.
629  *
630  *   Special control setup not covered by this function must be done after
631  *   using this function by direct modification of the CTRL and IRCTRL
632  *   registers.
633  *
634  *   Notice that pins used by the USART/UART module must be properly configured
635  *   by the user explicitly, in order for the USART/UART to work as intended.
636  *   (When configuring pins, one should remember to consider the sequence of
637  *   configuration, in order to avoid unintended pulses/glitches on output
638  *   pins.)
639  *
640  * @param[in] init
641  *   Pointer to initialization structure used to configure async IrDA setup.
642  *
643  * @note
644  *   This function only applies to USART0 as IrDA is not supported on the other
645  *   USART modules.
646  *
647  ******************************************************************************/
USART_InitIrDA(const USART_InitIrDA_TypeDef * init)648 void USART_InitIrDA(const USART_InitIrDA_TypeDef *init)
649 {
650   /* Init USART0 as async device */
651   USART_InitAsync(USART0, &(init->async));
652 
653   /* Set IrDA modulation to RZI (return-to-zero-inverted) */
654   USART0->CTRL |= USART_CTRL_TXINV;
655 
656   /* Invert Rx signal before demodulator if enabled */
657   if (init->irRxInv)
658   {
659     USART0->CTRL |= USART_CTRL_RXINV;
660   }
661 
662   /* Configure IrDA */
663   USART0->IRCTRL |= (uint32_t)init->irPw |
664                     (uint32_t)init->irPrsSel |
665                     ((uint32_t)init->irFilt << _USART_IRCTRL_IRFILT_SHIFT) |
666                     ((uint32_t)init->irPrsEn << _USART_IRCTRL_IRPRSEN_SHIFT);
667 
668   /* Enable IrDA */
669   USART0->IRCTRL |= USART_IRCTRL_IREN;
670 }
671 
672 
673 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
674 /***************************************************************************//**
675  * @brief
676  *   Init USART for I2S mode.
677  *
678  * @details
679  *   This function will configure basic settings in order to operate in I2S
680  *   mode.
681  *
682  *   Special control setup not covered by this function must be done after
683  *   using this function by direct modification of the CTRL and I2SCTRL
684  *   registers.
685  *
686  *   Notice that pins used by the USART module must be properly configured
687  *   by the user explicitly, in order for the USART to work as intended.
688  *   (When configuring pins, one should remember to consider the sequence of
689  *   configuration, in order to avoid unintended pulses/glitches on output
690  *   pins.)
691  *
692  * @param[in] usart
693  *   Pointer to USART peripheral register block. (UART does not support this
694  *   mode.)
695  *
696  * @param[in] init
697  *   Pointer to initialization structure used to configure basic I2S setup.
698  *
699  * @note
700  *   This function does not apply to all USART's. Refer to chip manuals.
701  *
702  ******************************************************************************/
USART_InitI2s(USART_TypeDef * usart,USART_InitI2s_TypeDef * init)703 void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init)
704 {
705   USART_Enable_TypeDef enable;
706 
707   /* Make sure the module exists on the selected chip */
708   EFM_ASSERT(USART_I2S_VALID(usart));
709 
710   /* Override the enable setting. */
711   enable            = init->sync.enable;
712   init->sync.enable = usartDisable;
713 
714   /* Init USART as a sync device. */
715   USART_InitSync(usart, &init->sync);
716 
717   /* Configure and enable I2CCTRL register acording to selected mode. */
718   usart->I2SCTRL = ((uint32_t)init->format) |
719                    ((uint32_t)init->justify) |
720                    (init->delay    ? USART_I2SCTRL_DELAY    : 0) |
721                    (init->dmaSplit ? USART_I2SCTRL_DMASPLIT : 0) |
722                    (init->mono     ? USART_I2SCTRL_MONO     : 0) |
723                    (USART_I2SCTRL_EN);
724 
725   if (enable != usartDisable)
726   {
727     USART_Enable(usart, enable);
728   }
729 }
730 
731 
732 /***************************************************************************//**
733  * @brief
734  *   Initialize automatic transmissions using PRS channel as trigger
735  * @note
736  *   Initialize USART with USART_Init() before setting up PRS configuration
737  *
738  * @param[in] usart Pointer to USART to configure
739  * @param[in] init Pointer to initialization structure
740  ******************************************************************************/
USART_InitPrsTrigger(USART_TypeDef * usart,const USART_PrsTriggerInit_TypeDef * init)741 void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init)
742 {
743   uint32_t trigctrl;
744 
745   /* Clear values that will be reconfigured  */
746   trigctrl = usart->TRIGCTRL & ~(_USART_TRIGCTRL_RXTEN_MASK|
747                                  _USART_TRIGCTRL_TXTEN_MASK|
748 #if defined(_EFM32_GIANT_FAMILY)
749                                  _USART_TRIGCTRL_AUTOTXTEN_MASK|
750 #endif
751                                  _USART_TRIGCTRL_TSEL_MASK);
752 
753 #if defined(_EFM32_GIANT_FAMILY)
754   if(init->autoTxTriggerEnable)
755   {
756     trigctrl |= USART_TRIGCTRL_AUTOTXTEN;
757   }
758 #endif
759   if(init->txTriggerEnable)
760   {
761     trigctrl |= USART_TRIGCTRL_TXTEN;
762   }
763   if(init->rxTriggerEnable)
764   {
765     trigctrl |= USART_TRIGCTRL_RXTEN;
766   }
767   trigctrl |= init->prsTriggerChannel;
768 
769   /* Enable new configuration */
770   usart->TRIGCTRL = trigctrl;
771 }
772 #endif
773 
774 
775 /***************************************************************************//**
776  * @brief
777  *   Reset USART/UART to same state as after a HW reset.
778  *
779  * @param[in] usart
780  *   Pointer to USART/UART peripheral register block.
781  ******************************************************************************/
USART_Reset(USART_TypeDef * usart)782 void USART_Reset(USART_TypeDef *usart)
783 {
784   /* Make sure the module exists on the selected chip */
785   EFM_ASSERT(USART_REF_VALID(usart)||UART_REF_VALID(usart));
786 
787   /* Make sure disabled first, before resetting other registers */
788   usart->CMD = USART_CMD_RXDIS | USART_CMD_TXDIS | USART_CMD_MASTERDIS |
789                USART_CMD_RXBLOCKDIS | USART_CMD_TXTRIDIS | USART_CMD_CLEARTX | USART_CMD_CLEARRX;
790   usart->CTRL     = _USART_CTRL_RESETVALUE;
791   usart->FRAME    = _USART_FRAME_RESETVALUE;
792   usart->TRIGCTRL = _USART_TRIGCTRL_RESETVALUE;
793   usart->CLKDIV   = _USART_CLKDIV_RESETVALUE;
794   usart->IEN      = _USART_IEN_RESETVALUE;
795   usart->IFC      = _USART_IFC_MASK;
796   usart->ROUTE    = _USART_ROUTE_RESETVALUE;
797 
798   if (USART_IRDA_VALID(usart))
799   {
800     usart->IRCTRL = _USART_IRCTRL_RESETVALUE;
801   }
802 
803 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
804   usart->INPUT = _USART_INPUT_RESETVALUE;
805 
806   if (USART_I2S_VALID(usart))
807   {
808     usart->I2SCTRL = _USART_I2SCTRL_RESETVALUE;
809   }
810 #endif
811 
812   /* Do not reset route register, setting should be done independently */
813 }
814 
815 
816 /***************************************************************************//**
817  * @brief
818  *   Receive one 4-8 bit frame, (or part of 10-16 bit frame).
819  *
820  * @details
821  *   This function is normally used to receive one frame when operating with
822  *   frame length 4-8 bits. Please refer to USART_RxExt() for reception of
823  *   9 bit frames.
824  *
825  *   Notice that possible parity/stop bits in asynchronous mode are not
826  *   considered part of specified frame bit length.
827  *
828  * @note
829  *   This function will stall if buffer is empty, until data is received.
830  *
831  * @param[in] usart
832  *   Pointer to USART/UART peripheral register block.
833  *
834  * @return
835  *   Data received.
836  ******************************************************************************/
USART_Rx(USART_TypeDef * usart)837 uint8_t USART_Rx(USART_TypeDef *usart)
838 {
839   while (!(usart->STATUS & USART_STATUS_RXDATAV))
840     ;
841 
842   return (uint8_t)(usart->RXDATA);
843 }
844 
845 
846 /***************************************************************************//**
847  * @brief
848  *   Receive two 4-8 bit frames, or one 10-16 bit frame.
849  *
850  * @details
851  *   This function is normally used to receive one frame when operating with
852  *   frame length 10-16 bits. Please refer to USART_RxDoubleExt() for reception
853  *   of two 9 bit frames.
854  *
855  *   Notice that possible parity/stop bits in asynchronous mode are not
856  *   considered part of specified frame bit length.
857  *
858  * @note
859  *   This function will stall if buffer is empty, until data is received.
860  *
861  * @param[in] usart
862  *   Pointer to USART/UART peripheral register block.
863  *
864  * @return
865  *   Data received.
866  ******************************************************************************/
USART_RxDouble(USART_TypeDef * usart)867 uint16_t USART_RxDouble(USART_TypeDef *usart)
868 {
869   while (!(usart->STATUS & USART_STATUS_RXFULL))
870     ;
871 
872   return (uint16_t)(usart->RXDOUBLE);
873 }
874 
875 
876 /***************************************************************************//**
877  * @brief
878  *   Receive two 4-9 bit frames, or one 10-16 bit frame with extended
879  *   information.
880  *
881  * @details
882  *   This function is normally used to receive one frame when operating with
883  *   frame length 10-16 bits and additional RX status information is required.
884  *
885  *   Notice that possible parity/stop bits in asynchronous mode are not
886  *   considered part of specified frame bit length.
887  *
888  * @note
889  *   This function will stall if buffer is empty, until data is received.
890  *
891  * @param[in] usart
892  *   Pointer to USART/UART peripheral register block.
893  *
894  * @return
895  *   Data received.
896  ******************************************************************************/
USART_RxDoubleExt(USART_TypeDef * usart)897 uint32_t USART_RxDoubleExt(USART_TypeDef *usart)
898 {
899   while (!(usart->STATUS & USART_STATUS_RXFULL))
900     ;
901 
902   return usart->RXDOUBLEX;
903 }
904 
905 
906 /***************************************************************************//**
907  * @brief
908  *   Receive one 4-9 bit frame, (or part of 10-16 bit frame) with extended
909  *   information.
910  *
911  * @details
912  *   This function is normally used to receive one frame when operating with
913  *   frame length 4-9 bits and additional RX status information is required.
914  *
915  *   Notice that possible parity/stop bits in asynchronous mode are not
916  *   considered part of specified frame bit length.
917  *
918  * @note
919  *   This function will stall if buffer is empty, until data is received.
920  *
921  * @param[in] usart
922  *   Pointer to USART/UART peripheral register block.
923  *
924  * @return
925  *   Data received.
926  ******************************************************************************/
USART_RxExt(USART_TypeDef * usart)927 uint16_t USART_RxExt(USART_TypeDef *usart)
928 {
929   while (!(usart->STATUS & USART_STATUS_RXDATAV))
930     ;
931 
932   return (uint16_t)(usart->RXDATAX);
933 }
934 
935 
936 /***************************************************************************//**
937  * @brief
938  *   Transmit one 4-9 bit frame.
939  *
940  * @details
941  *   Depending on frame length configuration, 4-8 (least significant) bits from
942  *   @p data are transmitted. If frame length is 9, 8 bits are transmitted from
943  *   @p data and one bit as specified by CTRL register, BIT8DV field. Please
944  *   refer to USART_TxExt() for transmitting 9 bit frame with full control of
945  *   all 9 bits.
946  *
947  *   Notice that possible parity/stop bits in asynchronous mode are not
948  *   considered part of specified frame bit length.
949  *
950  * @note
951  *   This function will stall if buffer is full, until buffer becomes available.
952  *
953  * @param[in] usart
954  *   Pointer to USART/UART peripheral register block.
955  *
956  * @param[in] data
957  *   Data to transmit. See details above for further info.
958  ******************************************************************************/
USART_Tx(USART_TypeDef * usart,uint8_t data)959 void USART_Tx(USART_TypeDef *usart, uint8_t data)
960 {
961   /* Check that transmit buffer is empty */
962   while (!(usart->STATUS & USART_STATUS_TXBL));
963   usart->TXDATA = (uint32_t)data;
964 }
965 
966 
967 /***************************************************************************//**
968  * @brief
969  *   Transmit two 4-9 bit frames, or one 10-16 bit frame.
970  *
971  * @details
972  *   Depending on frame length configuration, 4-8 (least significant) bits from
973  *   each byte in @p data are transmitted. If frame length is 9, 8 bits are
974  *   transmitted from each byte in @p data adding one bit as specified by CTRL
975  *   register, BIT8DV field, to each byte. Please refer to USART_TxDoubleExt()
976  *   for transmitting two 9 bit frames with full control of all 9 bits.
977  *
978  *   If frame length is 10-16, 10-16 (least significant) bits from @p data
979  *   are transmitted.
980  *
981  *   Notice that possible parity/stop bits in asynchronous mode are not
982  *   considered part of specified frame bit length.
983  *
984  * @note
985  *   This function will stall if buffer is full, until buffer becomes available.
986  *
987  * @param[in] usart
988  *   Pointer to USART/UART peripheral register block.
989  *
990  * @param[in] data
991  *   Data to transmit, the least significant byte holds the frame transmitted
992  *   first. See details above for further info.
993  ******************************************************************************/
USART_TxDouble(USART_TypeDef * usart,uint16_t data)994 void USART_TxDouble(USART_TypeDef *usart, uint16_t data)
995 {
996   /* Check that transmit buffer is empty */
997   while (!(usart->STATUS & USART_STATUS_TXBL))
998     ;
999   usart->TXDOUBLE = (uint32_t)data;
1000 }
1001 
1002 
1003 /***************************************************************************//**
1004  * @brief
1005  *   Transmit two 4-9 bit frames, or one 10-16 bit frame with extended control.
1006  *
1007  * @details
1008  *   Notice that possible parity/stop bits in asynchronous mode are not
1009  *   considered part of specified frame bit length.
1010  *
1011  * @note
1012  *   This function will stall if buffer is full, until buffer becomes available.
1013  *
1014  * @param[in] usart
1015  *   Pointer to USART/UART peripheral register block.
1016  *
1017  * @param[in] data
1018  *   Data to transmit with extended control. Contains two 16 bit words
1019  *   concatenated. Least significant word holds frame transitted first. If frame
1020  *   length is 4-9, two frames with 4-9 least significant bits from each 16 bit
1021  *   word are transmitted.
1022  * @par
1023  *   If frame length is 10-16 bits, 8 data bits are taken from the least
1024  *   significant 16 bit word, and the remaining bits from the other 16 bit word.
1025  * @par
1026  *   Additional control bits are available as documented in the EFM32 reference
1027  *   manual (set to 0 if not used). For 10-16 bit frame length, these control
1028  *   bits are taken from the most significant 16 bit word.
1029  ******************************************************************************/
USART_TxDoubleExt(USART_TypeDef * usart,uint32_t data)1030 void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data)
1031 {
1032   /* Check that transmit buffer is empty */
1033   while (!(usart->STATUS & USART_STATUS_TXBL))
1034     ;
1035   usart->TXDOUBLEX = data;
1036 }
1037 
1038 
1039 /***************************************************************************//**
1040  * @brief
1041  *   Transmit one 4-9 bit frame with extended control.
1042  *
1043  * @details
1044  *   Notice that possible parity/stop bits in asynchronous mode are not
1045  *   considered part of specified frame bit length.
1046  *
1047  * @note
1048  *   This function will stall if buffer is full, until buffer becomes available.
1049  *
1050  * @param[in] usart
1051  *   Pointer to USART/UART peripheral register block.
1052  *
1053  * @param[in] data
1054  *   Data to transmit with extended control. Least significant bits contains
1055  *   frame bits, and additional control bits are available as documented in
1056  *   the EFM32 reference manual (set to 0 if not used).
1057  ******************************************************************************/
USART_TxExt(USART_TypeDef * usart,uint16_t data)1058 void USART_TxExt(USART_TypeDef *usart, uint16_t data)
1059 {
1060   /* Check that transmit buffer is empty */
1061   while (!(usart->STATUS & USART_STATUS_TXBL))
1062     ;
1063   usart->TXDATAX = (uint32_t)data;
1064 }
1065 
1066 
1067 /** @} (end addtogroup USART) */
1068 /** @} (end addtogroup EM_Library) */
1069