1 /***************************************************************************//**
2 * @file
3 * @brief Universal synchronous/asynchronous receiver/transmitter (USART/UART)
4 * peripheral API
5 *******************************************************************************
6 * # License
7 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
8 *******************************************************************************
9 *
10 * SPDX-License-Identifier: Zlib
11 *
12 * The licensor of this software is Silicon Laboratories Inc.
13 *
14 * This software is provided 'as-is', without any express or implied
15 * warranty. In no event will the authors be held liable for any damages
16 * arising from the use of this software.
17 *
18 * Permission is granted to anyone to use this software for any purpose,
19 * including commercial applications, and to alter it and redistribute it
20 * freely, subject to the following restrictions:
21 *
22 * 1. The origin of this software must not be misrepresented; you must not
23 * claim that you wrote the original software. If you use this software
24 * in a product, an acknowledgment in the product documentation would be
25 * appreciated but is not required.
26 * 2. Altered source versions must be plainly marked as such, and must not be
27 * misrepresented as being the original software.
28 * 3. This notice may not be removed or altered from any source distribution.
29 *
30 ******************************************************************************/
31
32 #ifndef EM_USART_H
33 #define EM_USART_H
34
35 #include "em_device.h"
36 #if defined(USART_COUNT) && (USART_COUNT > 0)
37
38 #include <stdbool.h>
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 /***************************************************************************//**
45 * @addtogroup usart USART - Synchronous/Asynchronous Serial
46 * @brief Universal Synchronous/Asynchronous Receiver/Transmitter
47 * Peripheral API
48 * @details
49 * The Universal Synchronous/Asynchronous Receiver/Transmitter (USART)
50 * is a very flexible serial I/O module. It supports full duplex asynchronous UART
51 * communication as well as RS-485, SPI, MicroWire, and 3-wire. It can also interface
52 * with ISO7816 Smart-Cards, and IrDA devices.
53 *
54 * The USART has a wide selection of operating modes, frame formats, and baud rates.
55 * All features are supported through the API of this module.
56 *
57 * Triple buffering and DMA support makes high data-rates possible with minimal
58 * CPU intervention. It is possible to transmit and receive large frames while
59 * the MCU remains in EM1 Sleep.
60 *
61 * This module does not support DMA configuration. The UARTDRV and SPIDRV drivers
62 * provide full support for DMA and more.
63 *
64 * The following steps are necessary for basic operation:
65 *
66 * Clock enable:
67 * @include em_usart_clock_enable.c
68 *
69 * To initialize the USART for asynchronous operation (e.g., UART):
70 * @include em_usart_init_async.c
71 *
72 * To initialize the USART for synchronous operation (e.g., SPI):
73 * @include em_usart_init_sync.c
74 *
75 * After pins are assigned for the application/board, enable pins at the
76 * desired location. Available locations can be obtained from the Pin Definitions
77 * section in the data sheet.
78 * @if DOXYDOC_P1_DEVICE
79 * @include em_usart_route_p1.c
80 * @note UART hardware flow control is not directly supported in hardware on
81 * _SILICON_LABS_32B_SERIES_0 parts.
82 * @endif
83 * @if DOXYDOC_P2_DEVICE
84 * @include em_usart_route_p2.c
85 * @endif
86 * @note UARTDRV supports all types of UART flow control. Software assisted
87 * hardware flow control is available for parts without true UART hardware
88 * flow control.
89 * @{
90 ******************************************************************************/
91
92 /*******************************************************************************
93 ******************************** ENUMS ************************************
94 ******************************************************************************/
95
96 /** Databit selection. */
97 typedef enum {
98 usartDatabits4 = USART_FRAME_DATABITS_FOUR, /**< 4 data bits (not available for UART). */
99 usartDatabits5 = USART_FRAME_DATABITS_FIVE, /**< 5 data bits (not available for UART). */
100 usartDatabits6 = USART_FRAME_DATABITS_SIX, /**< 6 data bits (not available for UART). */
101 usartDatabits7 = USART_FRAME_DATABITS_SEVEN, /**< 7 data bits (not available for UART). */
102 usartDatabits8 = USART_FRAME_DATABITS_EIGHT, /**< 8 data bits. */
103 usartDatabits9 = USART_FRAME_DATABITS_NINE, /**< 9 data bits. */
104 usartDatabits10 = USART_FRAME_DATABITS_TEN, /**< 10 data bits (not available for UART). */
105 usartDatabits11 = USART_FRAME_DATABITS_ELEVEN, /**< 11 data bits (not available for UART). */
106 usartDatabits12 = USART_FRAME_DATABITS_TWELVE, /**< 12 data bits (not available for UART). */
107 usartDatabits13 = USART_FRAME_DATABITS_THIRTEEN, /**< 13 data bits (not available for UART). */
108 usartDatabits14 = USART_FRAME_DATABITS_FOURTEEN, /**< 14 data bits (not available for UART). */
109 usartDatabits15 = USART_FRAME_DATABITS_FIFTEEN, /**< 15 data bits (not available for UART). */
110 usartDatabits16 = USART_FRAME_DATABITS_SIXTEEN /**< 16 data bits (not available for UART). */
111 } USART_Databits_TypeDef;
112
113 /** Enable selection. */
114 typedef enum {
115 /** Disable both receiver and transmitter. */
116 usartDisable = 0x0,
117
118 /** Enable receiver only, transmitter disabled. */
119 usartEnableRx = USART_CMD_RXEN,
120
121 /** Enable transmitter only, receiver disabled. */
122 usartEnableTx = USART_CMD_TXEN,
123
124 /** Enable both receiver and transmitter. */
125 usartEnable = (USART_CMD_RXEN | USART_CMD_TXEN)
126 } USART_Enable_TypeDef;
127
128 /** Oversampling selection, used for asynchronous operation. */
129 typedef enum {
130 usartOVS16 = USART_CTRL_OVS_X16, /**< 16x oversampling (normal). */
131 usartOVS8 = USART_CTRL_OVS_X8, /**< 8x oversampling. */
132 usartOVS6 = USART_CTRL_OVS_X6, /**< 6x oversampling. */
133 usartOVS4 = USART_CTRL_OVS_X4 /**< 4x oversampling. */
134 } USART_OVS_TypeDef;
135
136 /** Parity selection, mainly used for asynchronous operation. */
137 typedef enum {
138 usartNoParity = USART_FRAME_PARITY_NONE, /**< No parity. */
139 usartEvenParity = USART_FRAME_PARITY_EVEN, /**< Even parity. */
140 usartOddParity = USART_FRAME_PARITY_ODD /**< Odd parity. */
141 } USART_Parity_TypeDef;
142
143 /** Stop bits selection, used for asynchronous operation. */
144 typedef enum {
145 usartStopbits0p5 = USART_FRAME_STOPBITS_HALF, /**< 0.5 stop bits. */
146 usartStopbits1 = USART_FRAME_STOPBITS_ONE, /**< 1 stop bits. */
147 usartStopbits1p5 = USART_FRAME_STOPBITS_ONEANDAHALF, /**< 1.5 stop bits. */
148 usartStopbits2 = USART_FRAME_STOPBITS_TWO /**< 2 stop bits. */
149 } USART_Stopbits_TypeDef;
150
151 #if defined(_USART_ROUTEPEN_RTSPEN_MASK) && defined(_USART_ROUTEPEN_CTSPEN_MASK)
152 /** Hardware Flow Control Selection. */
153 typedef enum {
154 /** No hardware flow control. */
155 usartHwFlowControlNone = 0,
156 /** CTS signal is enabled for TX flow control. */
157 usartHwFlowControlCts = USART_ROUTEPEN_CTSPEN,
158 /** RTS signal is enabled for RX flow control. */
159 usartHwFlowControlRts = USART_ROUTEPEN_RTSPEN,
160 /** CTS and RTS signals are enabled for TX and RX flow control. */
161 usartHwFlowControlCtsAndRts = USART_ROUTEPEN_CTSPEN | USART_ROUTEPEN_RTSPEN,
162 } USART_HwFlowControl_TypeDef;
163
164 #elif defined(USART_CTRLX_CTSEN)
165 /** Hardware Flow Control Selection. */
166 typedef enum {
167 /** No hardware flow control. */
168 usartHwFlowControlNone = 0,
169 /** CTS signal is enabled for TX flow control. */
170 usartHwFlowControlCts,
171 /** RTS signal is enabled for RX flow control. */
172 usartHwFlowControlRts,
173 /** CTS and RTS signals are enabled for TX and RX flow control. */
174 usartHwFlowControlCtsAndRts
175 } USART_HwFlowControl_TypeDef;
176 #endif
177
178 /** Clock polarity/phase mode. */
179 typedef enum {
180 /** Clock idle low, sample on rising edge. */
181 usartClockMode0 = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLELEADING,
182
183 /** Clock idle low, sample on falling edge. */
184 usartClockMode1 = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLETRAILING,
185
186 /** Clock idle high, sample on falling edge. */
187 usartClockMode2 = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLELEADING,
188
189 /** Clock idle high, sample on rising edge. */
190 usartClockMode3 = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLETRAILING
191 } USART_ClockMode_TypeDef;
192
193 /** Pulse width selection for IrDA mode. */
194 typedef enum {
195 /** IrDA pulse width is 1/16 for OVS=0 and 1/8 for OVS=1 */
196 usartIrDAPwONE = USART_IRCTRL_IRPW_ONE,
197
198 /** IrDA pulse width is 2/16 for OVS=0 and 2/8 for OVS=1 */
199 usartIrDAPwTWO = USART_IRCTRL_IRPW_TWO,
200
201 /** IrDA pulse width is 3/16 for OVS=0 and 3/8 for OVS=1 */
202 usartIrDAPwTHREE = USART_IRCTRL_IRPW_THREE,
203
204 /** IrDA pulse width is 4/16 for OVS=0 and 4/8 for OVS=1 */
205 usartIrDAPwFOUR = USART_IRCTRL_IRPW_FOUR
206 } USART_IrDAPw_Typedef;
207
208 /** PRS Channel type */
209 typedef uint8_t USART_PRS_Channel_t;
210
211 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
212 /** Deprecated PRS channel selector value.
213 * New code should use an integer instead. */
214 #define usartIrDAPrsCh0 0U
215 #define usartIrDAPrsCh1 1U
216 #define usartIrDAPrsCh2 2U
217 #define usartIrDAPrsCh3 3U
218 #define usartIrDAPrsCh4 4U
219 #define usartIrDAPrsCh5 5U
220 #define usartIrDAPrsCh6 6U
221 #define usartIrDAPrsCh7 7U
222 #define usartPrsRxCh0 0U
223 #define usartPrsRxCh1 1U
224 #define usartPrsRxCh2 2U
225 #define usartPrsRxCh3 3U
226 #define usartPrsRxCh4 4U
227 #define usartPrsRxCh5 5U
228 #define usartPrsRxCh6 6U
229 #define usartPrsRxCh7 7U
230 #define usartPrsRxCh8 8U
231 #define usartPrsRxCh9 9U
232 #define usartPrsRxCh10 10U
233 #define usartPrsRxCh11 11U
234 #define usartPrsTriggerCh0 0U
235 #define usartPrsTriggerCh1 1U
236 #define usartPrsTriggerCh2 2U
237 #define usartPrsTriggerCh3 3U
238 #define usartPrsTriggerCh4 4U
239 #define usartPrsTriggerCh5 5U
240 #define usartPrsTriggerCh6 6U
241 #define usartPrsTriggerCh7 7U
242 /** @endcond */
243
244 #if defined(_USART_I2SCTRL_MASK) && defined(USART_I2SCTRL_I2SEN)
245 /** I2S format selection. */
246 typedef enum {
247 usartI2sFormatW32D32 = USART_I2SCTRL_I2SFORMAT_W32D32, /**< 32-bit word, 32-bit data */
248 usartI2sFormatW32D24M = USART_I2SCTRL_I2SFORMAT_W32D24M, /**< 32-bit word, 32-bit data with 8 lsb masked */
249 usartI2sFormatW32D24 = USART_I2SCTRL_I2SFORMAT_W32D24, /**< 32-bit word, 24-bit data */
250 usartI2sFormatW32D16 = USART_I2SCTRL_I2SFORMAT_W32D16, /**< 32-bit word, 16-bit data */
251 usartI2sFormatW32D8 = USART_I2SCTRL_I2SFORMAT_W32D8, /**< 32-bit word, 8-bit data */
252 usartI2sFormatW16D16 = USART_I2SCTRL_I2SFORMAT_W16D16, /**< 16-bit word, 16-bit data */
253 usartI2sFormatW16D8 = USART_I2SCTRL_I2SFORMAT_W16D8, /**< 16-bit word, 8-bit data */
254 usartI2sFormatW8D8 = USART_I2SCTRL_I2SFORMAT_W8D8 /**< 8-bit word, 8-bit data */
255 } USART_I2sFormat_TypeDef;
256
257 /** I2S frame data justify. */
258 typedef enum {
259 usartI2sJustifyLeft = USART_I2SCTRL_I2SJUSTIFY_LEFT, /**< Data is left-justified within the frame */
260 usartI2sJustifyRight = USART_I2SCTRL_I2SJUSTIFY_RIGHT /**< Data is right-justified within the frame */
261 } USART_I2sJustify_TypeDef;
262
263 #elif defined(_USART_I2SCTRL_MASK)
264 /** I2S format selection. */
265 typedef enum {
266 usartI2sFormatW32D32 = USART_I2SCTRL_FORMAT_W32D32, /**< 32-bit word, 32-bit data. */
267 usartI2sFormatW32D24M = USART_I2SCTRL_FORMAT_W32D24M, /**< 32-bit word, 32-bit data with 8 lsb masked. */
268 usartI2sFormatW32D24 = USART_I2SCTRL_FORMAT_W32D24, /**< 32-bit word, 24-bit data. */
269 usartI2sFormatW32D16 = USART_I2SCTRL_FORMAT_W32D16, /**< 32-bit word, 16-bit data. */
270 usartI2sFormatW32D8 = USART_I2SCTRL_FORMAT_W32D8, /**< 32-bit word, 8-bit data. */
271 usartI2sFormatW16D16 = USART_I2SCTRL_FORMAT_W16D16, /**< 16-bit word, 16-bit data. */
272 usartI2sFormatW16D8 = USART_I2SCTRL_FORMAT_W16D8, /**< 16-bit word, 8-bit data. */
273 usartI2sFormatW8D8 = USART_I2SCTRL_FORMAT_W8D8 /**< 8-bit word, 8-bit data. */
274 } USART_I2sFormat_TypeDef;
275
276 /** I2S frame data justify. */
277 typedef enum {
278 usartI2sJustifyLeft = USART_I2SCTRL_JUSTIFY_LEFT, /**< Data is left-justified within the frame. */
279 usartI2sJustifyRight = USART_I2SCTRL_JUSTIFY_RIGHT /**< Data is right-justified within the frame. */
280 } USART_I2sJustify_TypeDef;
281 #endif
282
283 /*******************************************************************************
284 ******************************* STRUCTS ***********************************
285 ******************************************************************************/
286
287 /** Asynchronous mode initialization structure. */
288 typedef struct {
289 /** Specifies whether TX and/or RX is enabled when initialization is completed. */
290 USART_Enable_TypeDef enable;
291
292 /**
293 * USART/UART reference clock assumed when configuring baud rate setup.
294 * Set to 0 to use the currently configured reference clock.
295 */
296 uint32_t refFreq;
297
298 /** Desired baud rate. */
299 uint32_t baudrate;
300
301 /** Oversampling used. */
302 USART_OVS_TypeDef oversampling;
303
304 /** Number of data bits in frame. Notice that UART modules only support 8 or
305 * 9 data bits. */
306 USART_Databits_TypeDef databits;
307
308 /** Parity mode to use. */
309 USART_Parity_TypeDef parity;
310
311 /** Number of stop bits to use. */
312 USART_Stopbits_TypeDef stopbits;
313
314 #if !defined(_EFM32_GECKO_FAMILY)
315 /** Majority Vote Disable for 16x, 8x and 6x oversampling modes. */
316 bool mvdis;
317
318 /** Enable USART Rx via PRS. */
319 bool prsRxEnable;
320
321 /** Select PRS channel for USART Rx. (Only valid if prsRxEnable is true). */
322 USART_PRS_Channel_t prsRxCh;
323 #endif
324
325 /** Auto CS enabling. */
326 bool autoCsEnable;
327
328 /** Enable CS invert. By default, chip select is active low.
329 * Set to true to make chip select active high. */
330 bool csInv;
331
332 #if (_SILICON_LABS_32B_SERIES > 0)
333 /** Auto CS hold time in baud cycles. */
334 uint8_t autoCsHold;
335
336 /** Auto CS setup time in baud cycles. */
337 uint8_t autoCsSetup;
338
339 /** Hardware flow control mode. */
340 USART_HwFlowControl_TypeDef hwFlowControl;
341 #endif
342 } USART_InitAsync_TypeDef;
343
344 /** USART PRS trigger enable. */
345 typedef struct {
346 #if defined(USART_TRIGCTRL_AUTOTXTEN)
347 /** Enable AUTOTX. */
348 bool autoTxTriggerEnable;
349 #endif
350 /** Trigger receive via PRS channel. */
351 bool rxTriggerEnable;
352 /** Trigger transmit via PRS channel. */
353 bool txTriggerEnable;
354 /** PRS channel to be used to trigger auto transmission. */
355 USART_PRS_Channel_t prsTriggerChannel;
356 } USART_PrsTriggerInit_TypeDef;
357
358 /** Default configuration for USART asynchronous initialization structure. */
359 #if defined(_EFM32_GECKO_FAMILY)
360 /* Default USART Async struct for the EFM32G device */
361 #define USART_INITASYNC_DEFAULT \
362 { \
363 usartEnable, /* Enable RX/TX when initialization is complete. */ \
364 0, /* Use current configured reference clock for configuring baud rate. */ \
365 115200, /* 115200 bits/s. */ \
366 usartOVS16, /* 16x oversampling. */ \
367 usartDatabits8, /* 8 data bits. */ \
368 usartNoParity, /* No parity. */ \
369 usartStopbits1, /* 1 stop bit. */ \
370 false, /* Auto CS functionality enable/disable switch. */ \
371 false, /* No CS invert. */ \
372 }
373 #elif defined(_SILICON_LABS_32B_SERIES_0)
374 /* Default USART Async struct for Series 0 devices */
375 #define USART_INITASYNC_DEFAULT \
376 { \
377 usartEnable, /* Enable RX/TX when initialization is complete. */ \
378 0, /* Use current configured reference clock for configuring baud rate. */ \
379 115200, /* 115200 bits/s. */ \
380 usartOVS16, /* 16x oversampling. */ \
381 usartDatabits8, /* 8 data bits. */ \
382 usartNoParity, /* No parity. */ \
383 usartStopbits1, /* 1 stop bit. */ \
384 false, /* Do not disable majority vote. */ \
385 false, /* Not USART PRS input mode. */ \
386 0, /* PRS channel 0. */ \
387 false, /* Auto CS functionality enable/disable switch. */ \
388 false, /* No CS invert. */ \
389 }
390 #elif (_SILICON_LABS_32B_SERIES > 0)
391 /* Default USART Async struct for Series 1 and Series 2 devices */
392 #define USART_INITASYNC_DEFAULT \
393 { \
394 usartEnable, /* Enable RX/TX when initialization is complete. */ \
395 0, /* Use current configured reference clock for configuring baud rate. */ \
396 115200, /* 115200 bits/s. */ \
397 usartOVS16, /* 16x oversampling. */ \
398 usartDatabits8, /* 8 data bits. */ \
399 usartNoParity, /* No parity. */ \
400 usartStopbits1, /* 1 stop bit. */ \
401 false, /* Do not disable majority vote. */ \
402 false, /* Not USART PRS input mode. */ \
403 0, /* PRS channel 0. */ \
404 false, /* Auto CS functionality enable/disable switch */ \
405 false, /* No CS invert. */ \
406 0, /* Auto CS Hold cycles. */ \
407 0, /* Auto CS Setup cycles. */ \
408 usartHwFlowControlNone /* No HW flow control. */ \
409 }
410 #endif
411
412 /** Default configuration for USART PRS triggering structure. */
413 #if defined(USART_TRIGCTRL_AUTOTXTEN)
414 #define USART_INITPRSTRIGGER_DEFAULT \
415 { \
416 false, /* Do not enable autoTX triggering. */ \
417 false, /* Do not enable receive triggering. */ \
418 false, /* Do not enable transmit triggering. */ \
419 0 /* Set default channel to zero. */ \
420 }
421 #else
422 #define USART_INITPRSTRIGGER_DEFAULT \
423 { \
424 false, /* Do not enable receive triggering. */ \
425 false, /* Do not enable transmit triggering. */ \
426 0 /* Set default channel to zero. */ \
427 }
428 #endif
429
430 /** Synchronous mode initialization structure. */
431 typedef struct {
432 /** Specifies whether TX and/or RX shall be enabled when initialization is completed. */
433 USART_Enable_TypeDef enable;
434
435 /**
436 * USART/UART reference clock assumed when configuring baud rate setup.
437 * Set to 0 to use the currently configured reference clock.
438 */
439 uint32_t refFreq;
440
441 /** Desired baud rate. */
442 uint32_t baudrate;
443
444 /** Number of data bits in frame. */
445 USART_Databits_TypeDef databits;
446
447 /** Select if to operate in master or slave mode. */
448 bool master;
449
450 /** Select if to send most or least significant bit first. */
451 bool msbf;
452
453 /** Clock polarity/phase mode. */
454 USART_ClockMode_TypeDef clockMode;
455
456 #if !defined(_EFM32_GECKO_FAMILY)
457 /** Enable USART Rx via PRS. */
458 bool prsRxEnable;
459
460 /** Select PRS channel for USART Rx. (Only valid if prsRxEnable is true). */
461 USART_PRS_Channel_t prsRxCh;
462 #endif
463
464 #if defined(USART_TRIGCTRL_AUTOTXTEN)
465 /** Enable AUTOTX mode. Transmits as long as RX is not full.
466 * Generates underflows if TX is empty. */
467 bool autoTx;
468 #endif
469
470 /** Auto CS enabling */
471 bool autoCsEnable;
472
473 /** Enable CS invert. By default, chip select is active low.
474 * Set to true to make chip select active high. */
475 bool csInv;
476
477 #if defined(_USART_TIMING_CSHOLD_MASK)
478 /** Auto CS hold time in baud cycles */
479 uint8_t autoCsHold;
480
481 /** Auto CS setup time in baud cycles */
482 uint8_t autoCsSetup;
483 #endif
484 } USART_InitSync_TypeDef;
485
486 /** Default configuration for USART sync initialization structure. */
487 #if defined(_EFM32_GECKO_FAMILY)
488 /* Default USART Sync configuration for EFM32G devices. */
489 #define USART_INITSYNC_DEFAULT \
490 { \
491 usartEnable, /* Enable RX/TX when initialization is complete. */ \
492 0, /* Use current configured reference clock for configuring baud rate. */ \
493 1000000, /* 1 Mbits/s. */ \
494 usartDatabits8, /* 8 data bits. */ \
495 true, /* Master mode. */ \
496 false, /* Send least significant bit first. */ \
497 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
498 false, /* No AUTOCS mode. */ \
499 false, /* No CS invert. */ \
500 }
501 #elif defined(_SILICON_LABS_32B_SERIES_0)
502 /* Default USART Sync configuration for series 0 devices. */
503 #define USART_INITSYNC_DEFAULT \
504 { \
505 usartEnable, /* Enable RX/TX when initialization is complete. */ \
506 0, /* Use current configured reference clock for configuring baud rate. */ \
507 1000000, /* 1 Mbits/s. */ \
508 usartDatabits8, /* 8 data bits. */ \
509 true, /* Master mode. */ \
510 false, /* Send least significant bit first. */ \
511 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
512 false, /* Not USART PRS input mode. */ \
513 0, /* PRS channel 0. */ \
514 false, /* No AUTOTX mode. */ \
515 false, /* No AUTOCS mode. */ \
516 false, /* No CS invert. */ \
517 }
518 #elif (_SILICON_LABS_32B_SERIES > 0)
519 /* Default USART Sync configuration for series 2 devices */
520 #define USART_INITSYNC_DEFAULT \
521 { \
522 usartEnable, /* Enable RX/TX when initialization is complete. */ \
523 0, /* Use current configured reference clock for configuring baud rate. */ \
524 1000000, /* 1 Mbits/s. */ \
525 usartDatabits8, /* 8 databits. */ \
526 true, /* Master mode. */ \
527 false, /* Send least significant bit first. */ \
528 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
529 false, /* Not USART PRS input mode. */ \
530 0, /* PRS channel 0. */ \
531 false, /* No AUTOTX mode. */ \
532 false, /* No AUTOCS mode. */ \
533 false, /* No CS invert. */ \
534 0, /* Auto CS Hold cycles. */ \
535 0 /* Auto CS Setup cycles. */ \
536 }
537 #endif
538
539 /** IrDA mode initialization structure. Inherited from asynchronous mode initialization structure. */
540 typedef struct {
541 /** General Asynchronous initialization structure. */
542 USART_InitAsync_TypeDef async;
543
544 /** Set to invert Rx signal before IrDA demodulator. */
545 bool irRxInv;
546
547 /** Set to enable filter on IrDA demodulator. */
548 bool irFilt;
549
550 /** Configure the pulse width generated by the IrDA modulator as a fraction
551 * of the configured USART bit period. */
552 USART_IrDAPw_Typedef irPw;
553
554 #if defined(USART_IRCTRL_IRPRSEN)
555 /** Enable the PRS channel selected by irPrsSel as input to IrDA module
556 * instead of TX. */
557 bool irPrsEn;
558
559 /** PRS can be used as input to the pulse modulator instead of TX.
560 * This value selects the channel to use. */
561 USART_PRS_Channel_t irPrsSel;
562 #endif
563 } USART_InitIrDA_TypeDef;
564
565 /** Default configuration for IrDA mode initialization structure. */
566 #if defined(_EFM32_GECKO_FAMILY)
567 /* Default USART IrDA struct for the EFM32G device */
568 #define USART_INITIRDA_DEFAULT \
569 { \
570 { \
571 usartEnable, /* Enable RX/TX when initialization is complete. */ \
572 0, /* Use current configured reference clock for configuring baud rate. */ \
573 115200, /* 115200 bits/s. */ \
574 usartOVS16, /* 16x oversampling. */ \
575 usartDatabits8, /* 8 data bits. */ \
576 usartEvenParity, /* Even parity. */ \
577 usartStopbits1, /* 1 stop bit. */ \
578 false, /* Auto CS functionality enable/disable switch */ \
579 false, /* No CS invert. */ \
580 }, \
581 false, /* Rx invert disabled. */ \
582 false, /* Filtering disabled. */ \
583 usartIrDAPwTHREE, /* Pulse width is set to ONE. */ \
584 false, /* Routing to PRS is disabled. */ \
585 0 /* PRS channel 0. */ \
586 }
587 #elif defined(_SILICON_LABS_32B_SERIES_0)
588 /* Default USART IrDA struct for Series 0 devices */
589 #define USART_INITIRDA_DEFAULT \
590 { \
591 { \
592 usartEnable, /* Enable RX/TX when initialization is complete. */ \
593 0, /* Use current configured reference clock for configuring baud rate. */ \
594 115200, /* 115200 bits/s. */ \
595 usartOVS16, /* 16x oversampling. */ \
596 usartDatabits8, /* 8 data bits. */ \
597 usartEvenParity, /* Even parity. */ \
598 usartStopbits1, /* 1 stop bit. */ \
599 false, /* Do not disable majority vote. */ \
600 false, /* Not USART PRS input mode. */ \
601 0, /* PRS channel 0. */ \
602 false, /* Auto CS functionality enable/disable switch */ \
603 false, /* No CS invert. */ \
604 }, \
605 false, /* Rx invert disabled. */ \
606 false, /* Filtering disabled. */ \
607 usartIrDAPwTHREE, /* Pulse width is set to ONE. */ \
608 false, /* Routing to PRS is disabled. */ \
609 0 /* PRS channel 0. */ \
610 }
611 #elif (_SILICON_LABS_32B_SERIES > 0)
612 /* Default USART IrDA struct for Series 1 and Series 2 devices */
613 #if defined(USART_IRCTRL_IRPRSEN)
614 #define USART_INITIRDA_DEFAULT \
615 { \
616 { \
617 usartEnable, /* Enable RX/TX when initialization is complete. */ \
618 0, /* Use current configured reference clock for configuring baud rate. */ \
619 115200, /* 115200 bits/s. */ \
620 usartOVS16, /* 16x oversampling. */ \
621 usartDatabits8, /* 8 data bits. */ \
622 usartEvenParity, /* Even parity. */ \
623 usartStopbits1, /* 1 stop bit. */ \
624 false, /* Do not disable majority vote. */ \
625 false, /* Not USART PRS input mode. */ \
626 0, /* PRS channel 0. */ \
627 false, /* Auto CS functionality enable/disable switch */ \
628 false, /* No CS invert. */ \
629 0, /* Auto CS Hold cycles */ \
630 0, /* Auto CS Setup cycles */ \
631 usartHwFlowControlNone /* No HW flow control */ \
632 }, \
633 false, /* Rx invert disabled. */ \
634 false, /* Filtering disabled. */ \
635 usartIrDAPwTHREE, /* Pulse width is set to ONE. */ \
636 false, /* Routing to PRS is disabled. */ \
637 0 /* PRS channel 0. */ \
638 }
639 #else
640 #define USART_INITIRDA_DEFAULT \
641 { \
642 { \
643 usartEnable, /* Enable RX/TX when initialization is complete. */ \
644 0, /* Use current configured reference clock for configuring baud rate. */ \
645 115200, /* 115200 bits/s. */ \
646 usartOVS16, /* 16x oversampling. */ \
647 usartDatabits8, /* 8 data bits. */ \
648 usartEvenParity, /* Even parity. */ \
649 usartStopbits1, /* 1 stop bit. */ \
650 false, /* Do not disable majority vote. */ \
651 false, /* Not USART PRS input mode. */ \
652 0, /* PRS channel 0. */ \
653 false, /* Auto CS functionality enable/disable switch */ \
654 false, /* No CS invert. */ \
655 0, /* Auto CS Hold cycles */ \
656 0, /* Auto CS Setup cycles */ \
657 usartHwFlowControlNone /* No HW flow control */ \
658 }, \
659 false, /* Rx invert disabled. */ \
660 false, /* Filtering disabled. */ \
661 usartIrDAPwTHREE /* Pulse width is set to ONE. */ \
662 }
663 #endif
664 #endif
665
666 #if defined(_USART_I2SCTRL_MASK)
667 /** I2S mode initialization structure. Inherited from synchronous mode initialization structure. */
668 typedef struct {
669 /** General Synchronous initialization structure. */
670 USART_InitSync_TypeDef sync;
671
672 /** I2S mode. */
673 USART_I2sFormat_TypeDef format;
674
675 /** Delay on I2S data. Set to add a one-cycle delay between a transition
676 * on the word-clock and the start of the I2S word.
677 * Should be set for standard I2S format. */
678 bool delay;
679
680 /** Separate DMA Request For Left/Right Data. */
681 bool dmaSplit;
682
683 /** Justification of I2S data within the frame. */
684 USART_I2sJustify_TypeDef justify;
685
686 /** Stereo or Mono, set to true for mono. */
687 bool mono;
688 } USART_InitI2s_TypeDef;
689
690 /** Default configuration for I2S mode initialization structure. */
691 #if defined(_EFM32_GECKO_FAMILY)
692 /* Default USART Sync configuration for EFM32G devices. */
693 #define USART_INITI2S_DEFAULT \
694 { \
695 { \
696 usartEnable, /* Enable RX/TX when initialization is complete. */ \
697 0, /* Use current configured reference clock for configuring baud rate. */ \
698 1000000, /* 1 Mbits/s. */ \
699 usartDatabits16, /* 16 databits. */ \
700 true, /* Master mode. */ \
701 true, /* Most significant bit first. */ \
702 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
703 false, /* No AUTOCS mode */ \
704 false, /* No CS invert. */ \
705 }, \
706 usartI2sFormatW16D16, /* 16-bit word, 16-bit data */ \
707 true, /* Delay on I2S data. */ \
708 false, /* No DMA split. */ \
709 usartI2sJustifyLeft,/* Data is left-justified within the frame */ \
710 false /* Stereo mode. */ \
711 }
712 #elif defined(_SILICON_LABS_32B_SERIES_0)
713 /* Default USART Sync configuration for series 0 devices. */
714 #define USART_INITI2S_DEFAULT \
715 { \
716 { \
717 usartEnable, /* Enable RX/TX when initialization is complete. */ \
718 0, /* Use current configured reference clock for configuring baud rate. */ \
719 1000000, /* 1 Mbits/s. */ \
720 usartDatabits16, /* 16 databits. */ \
721 true, /* Master mode. */ \
722 true, /* Most significant bit first. */ \
723 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
724 false, /* Not USART PRS input mode. */ \
725 0, /* PRS channel 0. */ \
726 false, /* No AUTOTX mode. */ \
727 false, /* No AUTOCS mode */ \
728 false, /* No CS invert. */ \
729 }, \
730 usartI2sFormatW16D16, /* 16-bit word, 16-bit data */ \
731 true, /* Delay on I2S data. */ \
732 false, /* No DMA split. */ \
733 usartI2sJustifyLeft,/* Data is left-justified within the frame */ \
734 false /* Stereo mode. */ \
735 }
736 #elif (_SILICON_LABS_32B_SERIES > 0)
737 /* Default USART Sync configuration for series 2 devices */
738 #define USART_INITI2S_DEFAULT \
739 { \
740 { \
741 usartEnableTx, /* Enable TX when init completed. */ \
742 0, /* Use current configured reference clock for configuring baudrate. */ \
743 1000000, /* Baudrate 1M bits/s. */ \
744 usartDatabits16, /* 16 databits. */ \
745 true, /* Operate as I2S master. */ \
746 true, /* Most significant bit first. */ \
747 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
748 false, /* Don't enable USARTRx via PRS. */ \
749 usartPrsRxCh0, /* PRS channel selection (dummy). */ \
750 false, /* Disable AUTOTX mode. */ \
751 false, /* No AUTOCS mode */ \
752 false, /* No CS invert. */ \
753 0, /* Auto CS Hold cycles */ \
754 0 /* Auto CS Setup cycles */ \
755 }, \
756 usartI2sFormatW16D16, /* 16-bit word, 16-bit data */ \
757 true, /* Delay on I2S data. */ \
758 false, /* No DMA split. */ \
759 usartI2sJustifyLeft,/* Data is left-justified within the frame */ \
760 false /* Stereo mode. */ \
761 }
762 #endif
763 #endif
764
765 /*******************************************************************************
766 ***************************** PROTOTYPES **********************************
767 ******************************************************************************/
768
769 void USART_BaudrateAsyncSet(USART_TypeDef *usart,
770 uint32_t refFreq,
771 uint32_t baudrate,
772 USART_OVS_TypeDef ovs);
773 uint32_t USART_BaudrateCalc(uint32_t refFreq,
774 uint32_t clkdiv,
775 bool syncmode,
776 USART_OVS_TypeDef ovs);
777 uint32_t USART_BaudrateGet(USART_TypeDef *usart);
778 void USART_BaudrateSyncSet(USART_TypeDef *usart,
779 uint32_t refFreq,
780 uint32_t baudrate);
781 void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable);
782
783 void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init);
784 void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init);
785 void USARTn_InitIrDA(USART_TypeDef *usart, const USART_InitIrDA_TypeDef *init);
786
787 #if defined(_USART_I2SCTRL_MASK)
788 void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init);
789 #endif
790 void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init);
791
792 /***************************************************************************//**
793 * @brief
794 * Clear one or more pending USART interrupts.
795 *
796 * @param[in] usart
797 * Pointer to the USART/UART peripheral register block.
798 *
799 * @param[in] flags
800 * Pending USART/UART interrupt source(s) to clear. Use one or more valid
801 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
802 ******************************************************************************/
USART_IntClear(USART_TypeDef * usart,uint32_t flags)803 __STATIC_INLINE void USART_IntClear(USART_TypeDef *usart, uint32_t flags)
804 {
805 #if defined (USART_HAS_SET_CLEAR)
806 usart->IF_CLR = flags;
807 #else
808 usart->IFC = flags;
809 #endif
810 }
811
812 /***************************************************************************//**
813 * @brief
814 * Disable one or more USART interrupts.
815 *
816 * @param[in] usart
817 * Pointer to the USART/UART peripheral register block.
818 *
819 * @param[in] flags
820 * USART/UART interrupt source(s) to disable. Use one or more valid
821 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
822 ******************************************************************************/
USART_IntDisable(USART_TypeDef * usart,uint32_t flags)823 __STATIC_INLINE void USART_IntDisable(USART_TypeDef *usart, uint32_t flags)
824 {
825 usart->IEN &= ~flags;
826 }
827
828 /***************************************************************************//**
829 * @brief
830 * Enable one or more USART interrupts.
831 *
832 * @note
833 * Depending on the use, a pending interrupt may already be set prior to
834 * enabling the interrupt. To ignore a pending interrupt, consider using
835 * USART_IntClear() prior to enabling the interrupt.
836 *
837 * @param[in] usart
838 * Pointer to the USART/UART peripheral register block.
839 *
840 * @param[in] flags
841 * USART/UART interrupt source(s) to enable. Use one or more valid
842 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
843 ******************************************************************************/
USART_IntEnable(USART_TypeDef * usart,uint32_t flags)844 __STATIC_INLINE void USART_IntEnable(USART_TypeDef *usart, uint32_t flags)
845 {
846 usart->IEN |= flags;
847 }
848
849 /***************************************************************************//**
850 * @brief
851 * Get pending USART interrupt flags.
852 *
853 * @note
854 * The event bits are not cleared by the use of this function.
855 *
856 * @param[in] usart
857 * Pointer to the USART/UART peripheral register block.
858 *
859 * @return
860 * USART/UART interrupt source(s) pending. Returns one or more valid
861 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
862 ******************************************************************************/
USART_IntGet(USART_TypeDef * usart)863 __STATIC_INLINE uint32_t USART_IntGet(USART_TypeDef *usart)
864 {
865 return usart->IF;
866 }
867
868 /***************************************************************************//**
869 * @brief
870 * Get enabled and pending USART interrupt flags.
871 * Useful for handling more interrupt sources in the same interrupt handler.
872 *
873 * @param[in] usart
874 * Pointer to the USART/UART peripheral register block.
875 *
876 * @note
877 * Interrupt flags are not cleared by the use of this function.
878 *
879 * @return
880 * Pending and enabled USART interrupt sources.
881 * The return value is the bitwise AND combination of
882 * - the OR combination of enabled interrupt sources in USARTx_IEN_nnn
883 * register (USARTx_IEN_nnn) and
884 * - the OR combination of valid interrupt flags of the USART module
885 * (USARTx_IF_nnn).
886 ******************************************************************************/
USART_IntGetEnabled(USART_TypeDef * usart)887 __STATIC_INLINE uint32_t USART_IntGetEnabled(USART_TypeDef *usart)
888 {
889 uint32_t ien;
890
891 /* Store USARTx->IEN in temporary variable in order to define explicit order
892 * of volatile accesses. */
893 ien = usart->IEN;
894
895 /* Bitwise AND of pending and enabled interrupts. */
896 return usart->IF & ien;
897 }
898
899 /***************************************************************************//**
900 * @brief
901 * Set one or more pending USART interrupts from SW.
902 *
903 * @param[in] usart
904 * Pointer to the USART/UART peripheral register block.
905 *
906 * @param[in] flags
907 * USART/UART interrupt source(s) to set to pending. Use one or more valid
908 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
909 ******************************************************************************/
USART_IntSet(USART_TypeDef * usart,uint32_t flags)910 __STATIC_INLINE void USART_IntSet(USART_TypeDef *usart, uint32_t flags)
911 {
912 #if defined (USART_HAS_SET_CLEAR)
913 usart->IF_SET = flags;
914 #else
915 usart->IFS = flags;
916 #endif
917 }
918
919 /***************************************************************************//**
920 * @brief
921 * Get USART STATUS register.
922 *
923 * @param[in] usart
924 * Pointer to the USART/UART peripheral register block.
925 *
926 * @return
927 * STATUS register value.
928 *
929 ******************************************************************************/
USART_StatusGet(USART_TypeDef * usart)930 __STATIC_INLINE uint32_t USART_StatusGet(USART_TypeDef *usart)
931 {
932 return usart->STATUS;
933 }
934
935 void USART_Reset(USART_TypeDef *usart);
936 uint8_t USART_Rx(USART_TypeDef *usart);
937 uint16_t USART_RxDouble(USART_TypeDef *usart);
938 uint32_t USART_RxDoubleExt(USART_TypeDef *usart);
939 uint16_t USART_RxExt(USART_TypeDef *usart);
940
941 /***************************************************************************//**
942 * @brief
943 * Receive one 4-8 bit frame, (or part of 10-16 bit frame).
944 *
945 * @details
946 * This function is used to quickly receive one 4-8 bits frame by reading the
947 * RXDATA register directly, without checking the STATUS register for the
948 * RXDATAV flag. This can be useful from the RXDATAV interrupt handler,
949 * i.e., waiting is superfluous, in order to quickly read the received data.
950 * Please refer to @ref USART_RxDataXGet() for reception of 9 bit frames.
951 *
952 * @note
953 * Because this function does not check whether the RXDATA register actually
954 * holds valid data, it should only be used in situations when it is certain
955 * that there is valid data, ensured by some external program routine, e.g.,
956 * when handling an RXDATAV interrupt. The @ref USART_Rx() is normally a
957 * better choice if the validity of the RXDATA register is not certain.
958 *
959 * @note
960 * Notice that possible parity/stop bits in asynchronous mode are not
961 * considered part of specified frame bit length.
962 *
963 * @param[in] usart
964 * Pointer to USART/UART peripheral register block.
965 *
966 * @return
967 * Data received.
968 ******************************************************************************/
USART_RxDataGet(USART_TypeDef * usart)969 __STATIC_INLINE uint8_t USART_RxDataGet(USART_TypeDef *usart)
970 {
971 return (uint8_t)usart->RXDATA;
972 }
973
974 /***************************************************************************//**
975 * @brief
976 * Receive two 4-8 bit frames, or one 10-16 bit frame.
977 *
978 * @details
979 * This function is used to quickly receive one 10-16 bits frame or two 4-8
980 * bit frames by reading the RXDOUBLE register directly, without checking
981 * the STATUS register for the RXDATAV flag. This can be useful from the
982 * RXDATAV interrupt handler, i.e., waiting is superfluous, in order to
983 * quickly read the received data.
984 * This function is normally used to receive one frame when operating with
985 * frame length 10-16 bits. Please refer to @ref USART_RxDoubleXGet()
986 * for reception of two 9 bit frames.
987 *
988 * @note
989 * Because this function does not check whether the RXDOUBLE register actually
990 * holds valid data, it should only be used in situations when it is certain
991 * that there is valid data, ensured by some external program routine, e.g.,
992 * when handling an RXDATAV interrupt. The @ref USART_RxDouble() is
993 * normally a better choice if the validity of the RXDOUBLE register is not
994 * certain.
995 *
996 * @note
997 * Notice that possible parity/stop bits in asynchronous mode are not
998 * considered part of specified frame bit length.
999 *
1000 * @param[in] usart
1001 * Pointer to USART/UART peripheral register block.
1002 *
1003 * @return
1004 * Data received.
1005 ******************************************************************************/
USART_RxDoubleGet(USART_TypeDef * usart)1006 __STATIC_INLINE uint16_t USART_RxDoubleGet(USART_TypeDef *usart)
1007 {
1008 return (uint16_t)usart->RXDOUBLE;
1009 }
1010
1011 /***************************************************************************//**
1012 * @brief
1013 * Receive two 4-9 bit frames, or one 10-16 bit frame with extended
1014 * information.
1015 *
1016 * @details
1017 * This function is used to quickly receive one 10-16 bits frame or two 4-9
1018 * bit frames by reading the RXDOUBLEX register directly, without checking
1019 * the STATUS register for the RXDATAV flag. This can be useful from the
1020 * RXDATAV interrupt handler, i.e., waiting is superfluous, in order to
1021 * quickly read the received data.
1022 *
1023 * @note
1024 * Because this function does not check whether the RXDOUBLEX register actually
1025 * holds valid data, it should only be used in situations when it is certain
1026 * that there is valid data, ensured by some external program routine, e.g.,
1027 * when handling an RXDATAV interrupt. The @ref USART_RxDoubleExt() is
1028 * normally a better choice if the validity of the RXDOUBLEX register is not
1029 * certain.
1030 *
1031 * @note
1032 * Notice that possible parity/stop bits in asynchronous mode are not
1033 * considered part of specified frame bit length.
1034 *
1035 * @param[in] usart
1036 * Pointer to USART/UART peripheral register block.
1037 *
1038 * @return
1039 * Data received.
1040 ******************************************************************************/
USART_RxDoubleXGet(USART_TypeDef * usart)1041 __STATIC_INLINE uint32_t USART_RxDoubleXGet(USART_TypeDef *usart)
1042 {
1043 return usart->RXDOUBLEX;
1044 }
1045
1046 /***************************************************************************//**
1047 * @brief
1048 * Receive one 4-9 bit frame, (or part of 10-16 bit frame) with extended
1049 * information.
1050 *
1051 * @details
1052 * This function is used to quickly receive one 4-9 bit frame, (or part of
1053 * 10-16 bit frame) with extended information by reading the RXDATAX register
1054 * directly, without checking the STATUS register for the RXDATAV flag. This
1055 * can be useful from the RXDATAV interrupt handler, i.e., waiting is
1056 * superfluous, in order to quickly read the received data.
1057 *
1058 * @note
1059 * Because this function does not check whether the RXDATAX register actually
1060 * holds valid data, it should only be used in situations when it is certain
1061 * that there is valid data, ensured by some external program routine, e.g.,
1062 * when handling an RXDATAV interrupt. The @ref USART_RxExt() is normally
1063 * a better choice if the validity of the RXDATAX register is not certain.
1064 *
1065 * @note
1066 * Notice that possible parity/stop bits in asynchronous mode are not
1067 * considered part of specified frame bit length.
1068 *
1069 * @param[in] usart
1070 * Pointer to USART/UART peripheral register block.
1071 *
1072 * @return
1073 * Data received.
1074 ******************************************************************************/
USART_RxDataXGet(USART_TypeDef * usart)1075 __STATIC_INLINE uint16_t USART_RxDataXGet(USART_TypeDef *usart)
1076 {
1077 return (uint16_t)usart->RXDATAX;
1078 }
1079
1080 uint8_t USART_SpiTransfer(USART_TypeDef *usart, uint8_t data);
1081 void USART_Tx(USART_TypeDef *usart, uint8_t data);
1082 void USART_TxDouble(USART_TypeDef *usart, uint16_t data);
1083 void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data);
1084 void USART_TxExt(USART_TypeDef *usart, uint16_t data);
1085
1086 /** @} (end addtogroup usart) */
1087
1088 #ifdef __cplusplus
1089 }
1090 #endif
1091
1092 #endif /* defined(USART_COUNT) && (USART_COUNT > 0) */
1093 #endif /* EM_USART_H */
1094