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 usartHwFlowControlNone = 0,
155 usartHwFlowControlCts = USART_ROUTEPEN_CTSPEN,
156 usartHwFlowControlRts = USART_ROUTEPEN_RTSPEN,
157 usartHwFlowControlCtsAndRts = USART_ROUTEPEN_CTSPEN | USART_ROUTEPEN_RTSPEN,
158 } USART_HwFlowControl_TypeDef;
159
160 #elif defined(USART_CTRLX_CTSEN)
161 /** Hardware Flow Control Selection. */
162 typedef enum {
163 usartHwFlowControlNone = 0,
164 usartHwFlowControlCts,
165 usartHwFlowControlRts,
166 usartHwFlowControlCtsAndRts
167 } USART_HwFlowControl_TypeDef;
168 #endif
169
170 /** Clock polarity/phase mode. */
171 typedef enum {
172 /** Clock idle low, sample on rising edge. */
173 usartClockMode0 = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLELEADING,
174
175 /** Clock idle low, sample on falling edge. */
176 usartClockMode1 = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLETRAILING,
177
178 /** Clock idle high, sample on falling edge. */
179 usartClockMode2 = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLELEADING,
180
181 /** Clock idle high, sample on rising edge. */
182 usartClockMode3 = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLETRAILING
183 } USART_ClockMode_TypeDef;
184
185 /** Pulse width selection for IrDA mode. */
186 typedef enum {
187 /** IrDA pulse width is 1/16 for OVS=0 and 1/8 for OVS=1 */
188 usartIrDAPwONE = USART_IRCTRL_IRPW_ONE,
189
190 /** IrDA pulse width is 2/16 for OVS=0 and 2/8 for OVS=1 */
191 usartIrDAPwTWO = USART_IRCTRL_IRPW_TWO,
192
193 /** IrDA pulse width is 3/16 for OVS=0 and 3/8 for OVS=1 */
194 usartIrDAPwTHREE = USART_IRCTRL_IRPW_THREE,
195
196 /** IrDA pulse width is 4/16 for OVS=0 and 4/8 for OVS=1 */
197 usartIrDAPwFOUR = USART_IRCTRL_IRPW_FOUR
198 } USART_IrDAPw_Typedef;
199
200 /** PRS Channel type */
201 typedef uint8_t USART_PRS_Channel_t;
202
203 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
204 /** Deprecated PRS channel selector value.
205 * New code should use an integer instead. */
206 #define usartIrDAPrsCh0 0U
207 #define usartIrDAPrsCh1 1U
208 #define usartIrDAPrsCh2 2U
209 #define usartIrDAPrsCh3 3U
210 #define usartIrDAPrsCh4 4U
211 #define usartIrDAPrsCh5 5U
212 #define usartIrDAPrsCh6 6U
213 #define usartIrDAPrsCh7 7U
214 #define usartPrsRxCh0 0U
215 #define usartPrsRxCh1 1U
216 #define usartPrsRxCh2 2U
217 #define usartPrsRxCh3 3U
218 #define usartPrsRxCh4 4U
219 #define usartPrsRxCh5 5U
220 #define usartPrsRxCh6 6U
221 #define usartPrsRxCh7 7U
222 #define usartPrsRxCh8 8U
223 #define usartPrsRxCh9 9U
224 #define usartPrsRxCh10 10U
225 #define usartPrsRxCh11 11U
226 #define usartPrsTriggerCh0 0U
227 #define usartPrsTriggerCh1 1U
228 #define usartPrsTriggerCh2 2U
229 #define usartPrsTriggerCh3 3U
230 #define usartPrsTriggerCh4 4U
231 #define usartPrsTriggerCh5 5U
232 #define usartPrsTriggerCh6 6U
233 #define usartPrsTriggerCh7 7U
234 /** @endcond */
235
236 #if defined(_USART_I2SCTRL_MASK) && defined(USART_I2SCTRL_I2SEN)
237 /** I2S format selection. */
238 typedef enum {
239 usartI2sFormatW32D32 = USART_I2SCTRL_I2SFORMAT_W32D32, /**< 32-bit word, 32-bit data */
240 usartI2sFormatW32D24M = USART_I2SCTRL_I2SFORMAT_W32D24M, /**< 32-bit word, 32-bit data with 8 lsb masked */
241 usartI2sFormatW32D24 = USART_I2SCTRL_I2SFORMAT_W32D24, /**< 32-bit word, 24-bit data */
242 usartI2sFormatW32D16 = USART_I2SCTRL_I2SFORMAT_W32D16, /**< 32-bit word, 16-bit data */
243 usartI2sFormatW32D8 = USART_I2SCTRL_I2SFORMAT_W32D8, /**< 32-bit word, 8-bit data */
244 usartI2sFormatW16D16 = USART_I2SCTRL_I2SFORMAT_W16D16, /**< 16-bit word, 16-bit data */
245 usartI2sFormatW16D8 = USART_I2SCTRL_I2SFORMAT_W16D8, /**< 16-bit word, 8-bit data */
246 usartI2sFormatW8D8 = USART_I2SCTRL_I2SFORMAT_W8D8 /**< 8-bit word, 8-bit data */
247 } USART_I2sFormat_TypeDef;
248
249 /** I2S frame data justify. */
250 typedef enum {
251 usartI2sJustifyLeft = USART_I2SCTRL_I2SJUSTIFY_LEFT, /**< Data is left-justified within the frame */
252 usartI2sJustifyRight = USART_I2SCTRL_I2SJUSTIFY_RIGHT /**< Data is right-justified within the frame */
253 } USART_I2sJustify_TypeDef;
254
255 #elif defined(_USART_I2SCTRL_MASK)
256 /** I2S format selection. */
257 typedef enum {
258 usartI2sFormatW32D32 = USART_I2SCTRL_FORMAT_W32D32, /**< 32-bit word, 32-bit data. */
259 usartI2sFormatW32D24M = USART_I2SCTRL_FORMAT_W32D24M, /**< 32-bit word, 32-bit data with 8 lsb masked. */
260 usartI2sFormatW32D24 = USART_I2SCTRL_FORMAT_W32D24, /**< 32-bit word, 24-bit data. */
261 usartI2sFormatW32D16 = USART_I2SCTRL_FORMAT_W32D16, /**< 32-bit word, 16-bit data. */
262 usartI2sFormatW32D8 = USART_I2SCTRL_FORMAT_W32D8, /**< 32-bit word, 8-bit data. */
263 usartI2sFormatW16D16 = USART_I2SCTRL_FORMAT_W16D16, /**< 16-bit word, 16-bit data. */
264 usartI2sFormatW16D8 = USART_I2SCTRL_FORMAT_W16D8, /**< 16-bit word, 8-bit data. */
265 usartI2sFormatW8D8 = USART_I2SCTRL_FORMAT_W8D8 /**< 8-bit word, 8-bit data. */
266 } USART_I2sFormat_TypeDef;
267
268 /** I2S frame data justify. */
269 typedef enum {
270 usartI2sJustifyLeft = USART_I2SCTRL_JUSTIFY_LEFT, /**< Data is left-justified within the frame. */
271 usartI2sJustifyRight = USART_I2SCTRL_JUSTIFY_RIGHT /**< Data is right-justified within the frame. */
272 } USART_I2sJustify_TypeDef;
273 #endif
274
275 /*******************************************************************************
276 ******************************* STRUCTS ***********************************
277 ******************************************************************************/
278
279 /** Asynchronous mode initialization structure. */
280 typedef struct {
281 /** Specifies whether TX and/or RX is enabled when initialization is completed. */
282 USART_Enable_TypeDef enable;
283
284 /**
285 * USART/UART reference clock assumed when configuring baud rate setup.
286 * Set to 0 to use the currently configured reference clock.
287 */
288 uint32_t refFreq;
289
290 /** Desired baud rate. */
291 uint32_t baudrate;
292
293 /** Oversampling used. */
294 USART_OVS_TypeDef oversampling;
295
296 /** Number of data bits in frame. Notice that UART modules only support 8 or
297 * 9 data bits. */
298 USART_Databits_TypeDef databits;
299
300 /** Parity mode to use. */
301 USART_Parity_TypeDef parity;
302
303 /** Number of stop bits to use. */
304 USART_Stopbits_TypeDef stopbits;
305
306 #if !defined(_EFM32_GECKO_FAMILY)
307 /** Majority Vote Disable for 16x, 8x and 6x oversampling modes. */
308 bool mvdis;
309
310 /** Enable USART Rx via PRS. */
311 bool prsRxEnable;
312
313 /** Select PRS channel for USART Rx. (Only valid if prsRxEnable is true). */
314 USART_PRS_Channel_t prsRxCh;
315 #endif
316
317 /** Auto CS enabling. */
318 bool autoCsEnable;
319
320 #if (_SILICON_LABS_32B_SERIES > 0)
321 /** Auto CS hold time in baud cycles. */
322 uint8_t autoCsHold;
323
324 /** Auto CS setup time in baud cycles. */
325 uint8_t autoCsSetup;
326
327 /** Hardware flow control mode. */
328 USART_HwFlowControl_TypeDef hwFlowControl;
329 #endif
330 } USART_InitAsync_TypeDef;
331
332 /** USART PRS trigger enable. */
333 typedef struct {
334 #if defined(USART_TRIGCTRL_AUTOTXTEN)
335 /** Enable AUTOTX. */
336 bool autoTxTriggerEnable;
337 #endif
338 /** Trigger receive via PRS channel. */
339 bool rxTriggerEnable;
340 /** Trigger transmit via PRS channel. */
341 bool txTriggerEnable;
342 /** PRS channel to be used to trigger auto transmission. */
343 USART_PRS_Channel_t prsTriggerChannel;
344 } USART_PrsTriggerInit_TypeDef;
345
346 /** Default configuration for USART asynchronous initialization structure. */
347 #if defined(_EFM32_GECKO_FAMILY)
348 /* Default USART Async struct for the EFM32G device */
349 #define USART_INITASYNC_DEFAULT \
350 { \
351 usartEnable, /* Enable RX/TX when initialization is complete. */ \
352 0, /* Use current configured reference clock for configuring baud rate. */ \
353 115200, /* 115200 bits/s. */ \
354 usartOVS16, /* 16x oversampling. */ \
355 usartDatabits8, /* 8 data bits. */ \
356 usartNoParity, /* No parity. */ \
357 usartStopbits1, /* 1 stop bit. */ \
358 false, /* Auto CS functionality enable/disable switch */ \
359 }
360 #elif defined(_SILICON_LABS_32B_SERIES_0)
361 /* Default USART Async struct for Series 0 devices */
362 #define USART_INITASYNC_DEFAULT \
363 { \
364 usartEnable, /* Enable RX/TX when initialization is complete. */ \
365 0, /* Use current configured reference clock for configuring baud rate. */ \
366 115200, /* 115200 bits/s. */ \
367 usartOVS16, /* 16x oversampling. */ \
368 usartDatabits8, /* 8 data bits. */ \
369 usartNoParity, /* No parity. */ \
370 usartStopbits1, /* 1 stop bit. */ \
371 false, /* Do not disable majority vote. */ \
372 false, /* Not USART PRS input mode. */ \
373 0, /* PRS channel 0. */ \
374 false, /* Auto CS functionality enable/disable switch */ \
375 }
376 #elif (_SILICON_LABS_32B_SERIES > 0)
377 /* Default USART Async struct for Series 1 and Series 2 devices */
378 #define USART_INITASYNC_DEFAULT \
379 { \
380 usartEnable, /* Enable RX/TX when initialization is complete. */ \
381 0, /* Use current configured reference clock for configuring baud rate. */ \
382 115200, /* 115200 bits/s. */ \
383 usartOVS16, /* 16x oversampling. */ \
384 usartDatabits8, /* 8 data bits. */ \
385 usartNoParity, /* No parity. */ \
386 usartStopbits1, /* 1 stop bit. */ \
387 false, /* Do not disable majority vote. */ \
388 false, /* Not USART PRS input mode. */ \
389 0, /* PRS channel 0. */ \
390 false, /* Auto CS functionality enable/disable switch */ \
391 0, /* Auto CS Hold cycles */ \
392 0, /* Auto CS Setup cycles */ \
393 usartHwFlowControlNone /* No HW flow control */ \
394 }
395 #endif
396
397 /** Default configuration for USART PRS triggering structure. */
398 #if defined(USART_TRIGCTRL_AUTOTXTEN)
399 #define USART_INITPRSTRIGGER_DEFAULT \
400 { \
401 false, /* Do not enable autoTX triggering. */ \
402 false, /* Do not enable receive triggering. */ \
403 false, /* Do not enable transmit triggering. */ \
404 0 /* Set default channel to zero. */ \
405 }
406 #else
407 #define USART_INITPRSTRIGGER_DEFAULT \
408 { \
409 false, /* Do not enable receive triggering. */ \
410 false, /* Do not enable transmit triggering. */ \
411 0 /* Set default channel to zero. */ \
412 }
413 #endif
414
415 /** Synchronous mode initialization structure. */
416 typedef struct {
417 /** Specifies whether TX and/or RX shall be enabled when initialization is completed. */
418 USART_Enable_TypeDef enable;
419
420 /**
421 * USART/UART reference clock assumed when configuring baud rate setup.
422 * Set to 0 to use the currently configured reference clock.
423 */
424 uint32_t refFreq;
425
426 /** Desired baud rate. */
427 uint32_t baudrate;
428
429 /** Number of data bits in frame. */
430 USART_Databits_TypeDef databits;
431
432 /** Select if to operate in master or slave mode. */
433 bool master;
434
435 /** Select if to send most or least significant bit first. */
436 bool msbf;
437
438 /** Clock polarity/phase mode. */
439 USART_ClockMode_TypeDef clockMode;
440
441 #if !defined(_EFM32_GECKO_FAMILY)
442 /** Enable USART Rx via PRS. */
443 bool prsRxEnable;
444
445 /** Select PRS channel for USART Rx. (Only valid if prsRxEnable is true). */
446 USART_PRS_Channel_t prsRxCh;
447 #endif
448
449 #if defined(USART_TRIGCTRL_AUTOTXTEN)
450 /** Enable AUTOTX mode. Transmits as long as RX is not full.
451 * Generates underflows if TX is empty. */
452 bool autoTx;
453 #endif
454
455 /** Auto CS enabling */
456 bool autoCsEnable;
457
458 #if defined(_USART_TIMING_CSHOLD_MASK)
459 /** Auto CS hold time in baud cycles */
460 uint8_t autoCsHold;
461
462 /** Auto CS setup time in baud cycles */
463 uint8_t autoCsSetup;
464 #endif
465 } USART_InitSync_TypeDef;
466
467 /** Default configuration for USART sync initialization structure. */
468 #if defined(_EFM32_GECKO_FAMILY)
469 /* Default USART Sync configuration for EFM32G devices. */
470 #define USART_INITSYNC_DEFAULT \
471 { \
472 usartEnable, /* Enable RX/TX when initialization is complete. */ \
473 0, /* Use current configured reference clock for configuring baud rate. */ \
474 1000000, /* 1 Mbits/s. */ \
475 usartDatabits8, /* 8 data bits. */ \
476 true, /* Master mode. */ \
477 false, /* Send least significant bit first. */ \
478 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
479 false, /* No AUTOCS mode */ \
480 }
481 #elif defined(_SILICON_LABS_32B_SERIES_0)
482 /* Default USART Sync configuration for series 0 devices. */
483 #define USART_INITSYNC_DEFAULT \
484 { \
485 usartEnable, /* Enable RX/TX when initialization is complete. */ \
486 0, /* Use current configured reference clock for configuring baud rate. */ \
487 1000000, /* 1 Mbits/s. */ \
488 usartDatabits8, /* 8 data bits. */ \
489 true, /* Master mode. */ \
490 false, /* Send least significant bit first. */ \
491 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
492 false, /* Not USART PRS input mode. */ \
493 0, /* PRS channel 0. */ \
494 false, /* No AUTOTX mode. */ \
495 false, /* No AUTOCS mode */ \
496 }
497 #elif (_SILICON_LABS_32B_SERIES > 0)
498 /* Default USART Sync configuration for series 2 devices */
499 #define USART_INITSYNC_DEFAULT \
500 { \
501 usartEnable, /* Enable RX/TX when initialization is complete. */ \
502 0, /* Use current configured reference clock for configuring baud rate. */ \
503 1000000, /* 1 Mbits/s. */ \
504 usartDatabits8, /* 8 databits. */ \
505 true, /* Master mode. */ \
506 false, /* Send least significant bit first. */ \
507 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
508 false, /* Not USART PRS input mode. */ \
509 0, /* PRS channel 0. */ \
510 false, /* No AUTOTX mode. */ \
511 false, /* No AUTOCS mode. */ \
512 0, /* Auto CS Hold cycles. */ \
513 0 /* Auto CS Setup cycles. */ \
514 }
515 #endif
516
517 /** IrDA mode initialization structure. Inherited from asynchronous mode initialization structure. */
518 typedef struct {
519 /** General Asynchronous initialization structure. */
520 USART_InitAsync_TypeDef async;
521
522 /** Set to invert Rx signal before IrDA demodulator. */
523 bool irRxInv;
524
525 /** Set to enable filter on IrDA demodulator. */
526 bool irFilt;
527
528 /** Configure the pulse width generated by the IrDA modulator as a fraction
529 * of the configured USART bit period. */
530 USART_IrDAPw_Typedef irPw;
531
532 #if defined(USART_IRCTRL_IRPRSEN)
533 /** Enable the PRS channel selected by irPrsSel as input to IrDA module
534 * instead of TX. */
535 bool irPrsEn;
536
537 /** PRS can be used as input to the pulse modulator instead of TX.
538 * This value selects the channel to use. */
539 USART_PRS_Channel_t irPrsSel;
540 #endif
541 } USART_InitIrDA_TypeDef;
542
543 /** Default configuration for IrDA mode initialization structure. */
544 #if defined(_EFM32_GECKO_FAMILY)
545 /* Default USART IrDA struct for the EFM32G device */
546 #define USART_INITIRDA_DEFAULT \
547 { \
548 { \
549 usartEnable, /* Enable RX/TX when initialization is complete. */ \
550 0, /* Use current configured reference clock for configuring baud rate. */ \
551 115200, /* 115200 bits/s. */ \
552 usartOVS16, /* 16x oversampling. */ \
553 usartDatabits8, /* 8 data bits. */ \
554 usartEvenParity, /* Even parity. */ \
555 usartStopbits1, /* 1 stop bit. */ \
556 false, /* Auto CS functionality enable/disable switch */ \
557 }, \
558 false, /* Rx invert disabled. */ \
559 false, /* Filtering disabled. */ \
560 usartIrDAPwTHREE, /* Pulse width is set to ONE. */ \
561 false, /* Routing to PRS is disabled. */ \
562 0 /* PRS channel 0. */ \
563 }
564 #elif defined(_SILICON_LABS_32B_SERIES_0)
565 /* Default USART IrDA struct for Series 0 devices */
566 #define USART_INITIRDA_DEFAULT \
567 { \
568 { \
569 usartEnable, /* Enable RX/TX when initialization is complete. */ \
570 0, /* Use current configured reference clock for configuring baud rate. */ \
571 115200, /* 115200 bits/s. */ \
572 usartOVS16, /* 16x oversampling. */ \
573 usartDatabits8, /* 8 data bits. */ \
574 usartEvenParity, /* Even parity. */ \
575 usartStopbits1, /* 1 stop bit. */ \
576 false, /* Do not disable majority vote. */ \
577 false, /* Not USART PRS input mode. */ \
578 0, /* PRS channel 0. */ \
579 false, /* Auto CS functionality enable/disable switch */ \
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 (_SILICON_LABS_32B_SERIES > 0)
588 /* Default USART IrDA struct for Series 1 and Series 2 devices */
589 #if defined(USART_IRCTRL_IRPRSEN)
590 #define USART_INITIRDA_DEFAULT \
591 { \
592 { \
593 usartEnable, /* Enable RX/TX when initialization is complete. */ \
594 0, /* Use current configured reference clock for configuring baud rate. */ \
595 115200, /* 115200 bits/s. */ \
596 usartOVS16, /* 16x oversampling. */ \
597 usartDatabits8, /* 8 data bits. */ \
598 usartEvenParity, /* Even parity. */ \
599 usartStopbits1, /* 1 stop bit. */ \
600 false, /* Do not disable majority vote. */ \
601 false, /* Not USART PRS input mode. */ \
602 0, /* PRS channel 0. */ \
603 false, /* Auto CS functionality enable/disable switch */ \
604 0, /* Auto CS Hold cycles */ \
605 0, /* Auto CS Setup cycles */ \
606 usartHwFlowControlNone /* No HW flow control */ \
607 }, \
608 false, /* Rx invert disabled. */ \
609 false, /* Filtering disabled. */ \
610 usartIrDAPwTHREE, /* Pulse width is set to ONE. */ \
611 false, /* Routing to PRS is disabled. */ \
612 0 /* PRS channel 0. */ \
613 }
614 #else
615 #define USART_INITIRDA_DEFAULT \
616 { \
617 { \
618 usartEnable, /* Enable RX/TX when initialization is complete. */ \
619 0, /* Use current configured reference clock for configuring baud rate. */ \
620 115200, /* 115200 bits/s. */ \
621 usartOVS16, /* 16x oversampling. */ \
622 usartDatabits8, /* 8 data bits. */ \
623 usartEvenParity, /* Even parity. */ \
624 usartStopbits1, /* 1 stop bit. */ \
625 false, /* Do not disable majority vote. */ \
626 false, /* Not USART PRS input mode. */ \
627 0, /* PRS channel 0. */ \
628 false, /* Auto CS functionality enable/disable switch */ \
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 }
637 #endif
638 #endif
639
640 #if defined(_USART_I2SCTRL_MASK)
641 /** I2S mode initialization structure. Inherited from synchronous mode initialization structure. */
642 typedef struct {
643 /** General Synchronous initialization structure. */
644 USART_InitSync_TypeDef sync;
645
646 /** I2S mode. */
647 USART_I2sFormat_TypeDef format;
648
649 /** Delay on I2S data. Set to add a one-cycle delay between a transition
650 * on the word-clock and the start of the I2S word.
651 * Should be set for standard I2S format. */
652 bool delay;
653
654 /** Separate DMA Request For Left/Right Data. */
655 bool dmaSplit;
656
657 /** Justification of I2S data within the frame. */
658 USART_I2sJustify_TypeDef justify;
659
660 /** Stereo or Mono, set to true for mono. */
661 bool mono;
662 } USART_InitI2s_TypeDef;
663
664 /** Default configuration for I2S mode initialization structure. */
665 #if defined(_EFM32_GECKO_FAMILY)
666 /* Default USART Sync configuration for EFM32G devices. */
667 #define USART_INITI2S_DEFAULT \
668 { \
669 { \
670 usartEnable, /* Enable RX/TX when initialization is complete. */ \
671 0, /* Use current configured reference clock for configuring baud rate. */ \
672 1000000, /* 1 Mbits/s. */ \
673 usartDatabits16, /* 16 databits. */ \
674 true, /* Master mode. */ \
675 true, /* Most significant bit first. */ \
676 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
677 false, /* No AUTOCS mode */ \
678 }, \
679 usartI2sFormatW16D16, /* 16-bit word, 16-bit data */ \
680 true, /* Delay on I2S data. */ \
681 false, /* No DMA split. */ \
682 usartI2sJustifyLeft,/* Data is left-justified within the frame */ \
683 false /* Stereo mode. */ \
684 }
685 #elif defined(_SILICON_LABS_32B_SERIES_0)
686 /* Default USART Sync configuration for series 0 devices. */
687 #define USART_INITI2S_DEFAULT \
688 { \
689 { \
690 usartEnable, /* Enable RX/TX when initialization is complete. */ \
691 0, /* Use current configured reference clock for configuring baud rate. */ \
692 1000000, /* 1 Mbits/s. */ \
693 usartDatabits16, /* 16 databits. */ \
694 true, /* Master mode. */ \
695 true, /* Most significant bit first. */ \
696 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
697 false, /* Not USART PRS input mode. */ \
698 0, /* PRS channel 0. */ \
699 false, /* No AUTOTX mode. */ \
700 false, /* No AUTOCS mode */ \
701 }, \
702 usartI2sFormatW16D16, /* 16-bit word, 16-bit data */ \
703 true, /* Delay on I2S data. */ \
704 false, /* No DMA split. */ \
705 usartI2sJustifyLeft,/* Data is left-justified within the frame */ \
706 false /* Stereo mode. */ \
707 }
708 #elif (_SILICON_LABS_32B_SERIES > 0)
709 /* Default USART Sync configuration for series 2 devices */
710 #define USART_INITI2S_DEFAULT \
711 { \
712 { \
713 usartEnableTx, /* Enable TX when init completed. */ \
714 0, /* Use current configured reference clock for configuring baudrate. */ \
715 1000000, /* Baudrate 1M bits/s. */ \
716 usartDatabits16, /* 16 databits. */ \
717 true, /* Operate as I2S master. */ \
718 true, /* Most significant bit first. */ \
719 usartClockMode0, /* Clock idle low, sample on rising edge. */ \
720 false, /* Don't enable USARTRx via PRS. */ \
721 usartPrsRxCh0, /* PRS channel selection (dummy). */ \
722 false, /* Disable AUTOTX mode. */ \
723 false, /* No AUTOCS mode */ \
724 0, /* Auto CS Hold cycles */ \
725 0 /* Auto CS Setup cycles */ \
726 }, \
727 usartI2sFormatW16D16, /* 16-bit word, 16-bit data */ \
728 true, /* Delay on I2S data. */ \
729 false, /* No DMA split. */ \
730 usartI2sJustifyLeft,/* Data is left-justified within the frame */ \
731 false /* Stereo mode. */ \
732 }
733 #endif
734 #endif
735
736 /*******************************************************************************
737 ***************************** PROTOTYPES **********************************
738 ******************************************************************************/
739
740 void USART_BaudrateAsyncSet(USART_TypeDef *usart,
741 uint32_t refFreq,
742 uint32_t baudrate,
743 USART_OVS_TypeDef ovs);
744 uint32_t USART_BaudrateCalc(uint32_t refFreq,
745 uint32_t clkdiv,
746 bool syncmode,
747 USART_OVS_TypeDef ovs);
748 uint32_t USART_BaudrateGet(USART_TypeDef *usart);
749 void USART_BaudrateSyncSet(USART_TypeDef *usart,
750 uint32_t refFreq,
751 uint32_t baudrate);
752 void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable);
753
754 void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init);
755 void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init);
756 void USARTn_InitIrDA(USART_TypeDef *usart, const USART_InitIrDA_TypeDef *init);
757
758 #if defined(_USART_I2SCTRL_MASK)
759 void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init);
760 #endif
761 void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init);
762
763 /***************************************************************************//**
764 * @brief
765 * Clear one or more pending USART interrupts.
766 *
767 * @param[in] usart
768 * Pointer to USART/UART peripheral register block.
769 *
770 * @param[in] flags
771 * Pending USART/UART interrupt source(s) to clear. Use one or more valid
772 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
773 ******************************************************************************/
USART_IntClear(USART_TypeDef * usart,uint32_t flags)774 __STATIC_INLINE void USART_IntClear(USART_TypeDef *usart, uint32_t flags)
775 {
776 #if defined (USART_HAS_SET_CLEAR)
777 usart->IF_CLR = flags;
778 #else
779 usart->IFC = flags;
780 #endif
781 }
782
783 /***************************************************************************//**
784 * @brief
785 * Disable one or more USART interrupts.
786 *
787 * @param[in] usart
788 * Pointer to USART/UART peripheral register block.
789 *
790 * @param[in] flags
791 * USART/UART interrupt source(s) to disable. Use one or more valid
792 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
793 ******************************************************************************/
USART_IntDisable(USART_TypeDef * usart,uint32_t flags)794 __STATIC_INLINE void USART_IntDisable(USART_TypeDef *usart, uint32_t flags)
795 {
796 usart->IEN &= ~flags;
797 }
798
799 /***************************************************************************//**
800 * @brief
801 * Enable one or more USART interrupts.
802 *
803 * @note
804 * Depending on the use, a pending interrupt may already be set prior to
805 * enabling the interrupt. To ignore a pending interrupt, consider using
806 * USART_IntClear() prior to enabling the interrupt.
807 *
808 * @param[in] usart
809 * Pointer to USART/UART peripheral register block.
810 *
811 * @param[in] flags
812 * USART/UART interrupt source(s) to enable. Use one or more valid
813 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
814 ******************************************************************************/
USART_IntEnable(USART_TypeDef * usart,uint32_t flags)815 __STATIC_INLINE void USART_IntEnable(USART_TypeDef *usart, uint32_t flags)
816 {
817 usart->IEN |= flags;
818 }
819
820 /***************************************************************************//**
821 * @brief
822 * Get pending USART interrupt flags.
823 *
824 * @note
825 * The event bits are not cleared by the use of this function.
826 *
827 * @param[in] usart
828 * Pointer to USART/UART peripheral register block.
829 *
830 * @return
831 * USART/UART interrupt source(s) pending. Returns one or more valid
832 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
833 ******************************************************************************/
USART_IntGet(USART_TypeDef * usart)834 __STATIC_INLINE uint32_t USART_IntGet(USART_TypeDef *usart)
835 {
836 return usart->IF;
837 }
838
839 /***************************************************************************//**
840 * @brief
841 * Get enabled and pending USART interrupt flags.
842 * Useful for handling more interrupt sources in the same interrupt handler.
843 *
844 * @param[in] usart
845 * Pointer to USART/UART peripheral register block.
846 *
847 * @note
848 * Interrupt flags are not cleared by the use of this function.
849 *
850 * @return
851 * Pending and enabled USART interrupt sources.
852 * The return value is the bitwise AND combination of
853 * - the OR combination of enabled interrupt sources in USARTx_IEN_nnn
854 * register (USARTx_IEN_nnn) and
855 * - the OR combination of valid interrupt flags of the USART module
856 * (USARTx_IF_nnn).
857 ******************************************************************************/
USART_IntGetEnabled(USART_TypeDef * usart)858 __STATIC_INLINE uint32_t USART_IntGetEnabled(USART_TypeDef *usart)
859 {
860 uint32_t ien;
861
862 /* Store USARTx->IEN in temporary variable in order to define explicit order
863 * of volatile accesses. */
864 ien = usart->IEN;
865
866 /* Bitwise AND of pending and enabled interrupts. */
867 return usart->IF & ien;
868 }
869
870 /***************************************************************************//**
871 * @brief
872 * Set one or more pending USART interrupts from SW.
873 *
874 * @param[in] usart
875 * Pointer to USART/UART peripheral register block.
876 *
877 * @param[in] flags
878 * USART/UART interrupt source(s) to set to pending. Use one or more valid
879 * interrupt flags for the USART module (USART_IF_nnn) OR'ed together.
880 ******************************************************************************/
USART_IntSet(USART_TypeDef * usart,uint32_t flags)881 __STATIC_INLINE void USART_IntSet(USART_TypeDef *usart, uint32_t flags)
882 {
883 #if defined (USART_HAS_SET_CLEAR)
884 usart->IF_SET = flags;
885 #else
886 usart->IFS = flags;
887 #endif
888 }
889
890 /***************************************************************************//**
891 * @brief
892 * Get USART STATUS register.
893 *
894 * @param[in] usart
895 * Pointer to USART/UART peripheral register block.
896 *
897 * @return
898 * STATUS register value.
899 *
900 ******************************************************************************/
USART_StatusGet(USART_TypeDef * usart)901 __STATIC_INLINE uint32_t USART_StatusGet(USART_TypeDef *usart)
902 {
903 return usart->STATUS;
904 }
905
906 void USART_Reset(USART_TypeDef *usart);
907 uint8_t USART_Rx(USART_TypeDef *usart);
908 uint16_t USART_RxDouble(USART_TypeDef *usart);
909 uint32_t USART_RxDoubleExt(USART_TypeDef *usart);
910 uint16_t USART_RxExt(USART_TypeDef *usart);
911
912 /***************************************************************************//**
913 * @brief
914 * Receive one 4-8 bit frame, (or part of 10-16 bit frame).
915 *
916 * @details
917 * This function is used to quickly receive one 4-8 bits frame by reading the
918 * RXDATA register directly, without checking the STATUS register for the
919 * RXDATAV flag. This can be useful from the RXDATAV interrupt handler,
920 * i.e., waiting is superfluous, in order to quickly read the received data.
921 * Please refer to @ref USART_RxDataXGet() for reception of 9 bit frames.
922 *
923 * @note
924 * Since this function does not check whether the RXDATA register actually
925 * holds valid data, it should only be used in situations when it is certain
926 * that there is valid data, ensured by some external program routine, e.g.,
927 * when handling an RXDATAV interrupt. The @ref USART_Rx() is normally a
928 * better choice if the validity of the RXDATA register is not certain.
929 *
930 * @note
931 * Notice that possible parity/stop bits in asynchronous mode are not
932 * considered part of specified frame bit length.
933 *
934 * @param[in] usart
935 * Pointer to USART/UART peripheral register block.
936 *
937 * @return
938 * Data received.
939 ******************************************************************************/
USART_RxDataGet(USART_TypeDef * usart)940 __STATIC_INLINE uint8_t USART_RxDataGet(USART_TypeDef *usart)
941 {
942 return (uint8_t)usart->RXDATA;
943 }
944
945 /***************************************************************************//**
946 * @brief
947 * Receive two 4-8 bit frames, or one 10-16 bit frame.
948 *
949 * @details
950 * This function is used to quickly receive one 10-16 bits frame or two 4-8
951 * bit frames by reading the RXDOUBLE register directly, without checking
952 * the STATUS register for the RXDATAV flag. This can be useful from the
953 * RXDATAV interrupt handler, i.e., waiting is superfluous, in order to
954 * quickly read the received data.
955 * This function is normally used to receive one frame when operating with
956 * frame length 10-16 bits. Please refer to @ref USART_RxDoubleXGet()
957 * for reception of two 9 bit frames.
958 *
959 * @note
960 * Since this function does not check whether the RXDOUBLE register actually
961 * holds valid data, it should only be used in situations when it is certain
962 * that there is valid data, ensured by some external program routine, e.g.,
963 * when handling an RXDATAV interrupt. The @ref USART_RxDouble() is
964 * normally a better choice if the validity of the RXDOUBLE register is not
965 * certain.
966 *
967 * @note
968 * Notice that possible parity/stop bits in asynchronous mode are not
969 * considered part of specified frame bit length.
970 *
971 * @param[in] usart
972 * Pointer to USART/UART peripheral register block.
973 *
974 * @return
975 * Data received.
976 ******************************************************************************/
USART_RxDoubleGet(USART_TypeDef * usart)977 __STATIC_INLINE uint16_t USART_RxDoubleGet(USART_TypeDef *usart)
978 {
979 return (uint16_t)usart->RXDOUBLE;
980 }
981
982 /***************************************************************************//**
983 * @brief
984 * Receive two 4-9 bit frames, or one 10-16 bit frame with extended
985 * information.
986 *
987 * @details
988 * This function is used to quickly receive one 10-16 bits frame or two 4-9
989 * bit frames by reading the RXDOUBLEX register directly, without checking
990 * the STATUS register for the RXDATAV flag. This can be useful from the
991 * RXDATAV interrupt handler, i.e., waiting is superfluous, in order to
992 * quickly read the received data.
993 *
994 * @note
995 * Since this function does not check whether the RXDOUBLEX register actually
996 * holds valid data, it should only be used in situations when it is certain
997 * that there is valid data, ensured by some external program routine, e.g.,
998 * when handling an RXDATAV interrupt. The @ref USART_RxDoubleExt() is
999 * normally a better choice if the validity of the RXDOUBLEX register is not
1000 * certain.
1001 *
1002 * @note
1003 * Notice that possible parity/stop bits in asynchronous mode are not
1004 * considered part of specified frame bit length.
1005 *
1006 * @param[in] usart
1007 * Pointer to USART/UART peripheral register block.
1008 *
1009 * @return
1010 * Data received.
1011 ******************************************************************************/
USART_RxDoubleXGet(USART_TypeDef * usart)1012 __STATIC_INLINE uint32_t USART_RxDoubleXGet(USART_TypeDef *usart)
1013 {
1014 return usart->RXDOUBLEX;
1015 }
1016
1017 /***************************************************************************//**
1018 * @brief
1019 * Receive one 4-9 bit frame, (or part of 10-16 bit frame) with extended
1020 * information.
1021 *
1022 * @details
1023 * This function is used to quickly receive one 4-9 bit frame, (or part of
1024 * 10-16 bit frame) with extended information by reading the RXDATAX register
1025 * directly, without checking the STATUS register for the RXDATAV flag. This
1026 * can be useful from the RXDATAV interrupt handler, i.e., waiting is
1027 * superfluous, in order to quickly read the received data.
1028 *
1029 * @note
1030 * Since this function does not check whether the RXDATAX register actually
1031 * holds valid data, it should only be used in situations when it is certain
1032 * that there is valid data, ensured by some external program routine, e.g.,
1033 * when handling an RXDATAV interrupt. The @ref USART_RxExt() is normally
1034 * a better choice if the validity of the RXDATAX register is not certain.
1035 *
1036 * @note
1037 * Notice that possible parity/stop bits in asynchronous mode are not
1038 * considered part of specified frame bit length.
1039 *
1040 * @param[in] usart
1041 * Pointer to USART/UART peripheral register block.
1042 *
1043 * @return
1044 * Data received.
1045 ******************************************************************************/
USART_RxDataXGet(USART_TypeDef * usart)1046 __STATIC_INLINE uint16_t USART_RxDataXGet(USART_TypeDef *usart)
1047 {
1048 return (uint16_t)usart->RXDATAX;
1049 }
1050
1051 uint8_t USART_SpiTransfer(USART_TypeDef *usart, uint8_t data);
1052 void USART_Tx(USART_TypeDef *usart, uint8_t data);
1053 void USART_TxDouble(USART_TypeDef *usart, uint16_t data);
1054 void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data);
1055 void USART_TxExt(USART_TypeDef *usart, uint16_t data);
1056
1057 /** @} (end addtogroup usart) */
1058
1059 #ifdef __cplusplus
1060 }
1061 #endif
1062
1063 #endif /* defined(USART_COUNT) && (USART_COUNT > 0) */
1064 #endif /* EM_USART_H */
1065