]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_usart.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS / Demo / CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso / NXP_Code / drivers / fsl_usart.c
1 /*\r
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.\r
3  * Copyright 2016-2019 NXP\r
4  * All rights reserved.\r
5  *\r
6  * SPDX-License-Identifier: BSD-3-Clause\r
7  */\r
8 \r
9 #include "fsl_usart.h"\r
10 #include "fsl_device_registers.h"\r
11 #include "fsl_flexcomm.h"\r
12 \r
13 /*******************************************************************************\r
14  * Definitions\r
15  ******************************************************************************/\r
16 \r
17 /* Component ID definition, used by tools. */\r
18 #ifndef FSL_COMPONENT_ID\r
19 #define FSL_COMPONENT_ID "platform.drivers.flexcomm_usart"\r
20 #endif\r
21 \r
22 /*!\r
23  * @brief Used for conversion from `flexcomm_usart_irq_handler_t` to `flexcomm_irq_handler_t`\r
24  */\r
25 typedef union usart_to_flexcomm\r
26 {\r
27     flexcomm_usart_irq_handler_t usart_master_handler;\r
28     flexcomm_irq_handler_t flexcomm_handler;\r
29 } usart_to_flexcomm_t;\r
30 \r
31 enum\r
32 {\r
33     kUSART_TxIdle, /* TX idle. */\r
34     kUSART_TxBusy, /* TX busy. */\r
35     kUSART_RxIdle, /* RX idle. */\r
36     kUSART_RxBusy  /* RX busy. */\r
37 };\r
38 \r
39 /*******************************************************************************\r
40  * Variables\r
41  ******************************************************************************/\r
42 \r
43 /*! @brief IRQ name array */\r
44 static const IRQn_Type s_usartIRQ[] = USART_IRQS;\r
45 \r
46 /*! @brief Array to map USART instance number to base address. */\r
47 static const uint32_t s_usartBaseAddrs[FSL_FEATURE_SOC_USART_COUNT] = USART_BASE_ADDRS;\r
48 \r
49 /*******************************************************************************\r
50  * Code\r
51  ******************************************************************************/\r
52 \r
53 /* Get the index corresponding to the USART */\r
54 /*! brief Returns instance number for USART peripheral base address. */\r
55 uint32_t USART_GetInstance(USART_Type *base)\r
56 {\r
57     uint32_t i;\r
58 \r
59     for (i = 0; i < (uint32_t)FSL_FEATURE_SOC_USART_COUNT; i++)\r
60     {\r
61         if ((uint32_t)base == s_usartBaseAddrs[i])\r
62         {\r
63             break;\r
64         }\r
65     }\r
66 \r
67     assert(i < FSL_FEATURE_SOC_USART_COUNT);\r
68     return i;\r
69 }\r
70 \r
71 /*!\r
72  * brief Get the length of received data in RX ring buffer.\r
73  *\r
74  * param handle USART handle pointer.\r
75  * return Length of received data in RX ring buffer.\r
76  */\r
77 size_t USART_TransferGetRxRingBufferLength(usart_handle_t *handle)\r
78 {\r
79     size_t size;\r
80 \r
81     /* Check arguments */\r
82     assert(NULL != handle);\r
83     uint16_t rxRingBufferHead = handle->rxRingBufferHead;\r
84     uint16_t rxRingBufferTail = handle->rxRingBufferTail;\r
85 \r
86     if (rxRingBufferTail > rxRingBufferHead)\r
87     {\r
88         size = (size_t)rxRingBufferHead + handle->rxRingBufferSize - (size_t)rxRingBufferTail;\r
89     }\r
90     else\r
91     {\r
92         size = (size_t)rxRingBufferHead - (size_t)rxRingBufferTail;\r
93     }\r
94     return size;\r
95 }\r
96 \r
97 static bool USART_TransferIsRxRingBufferFull(usart_handle_t *handle)\r
98 {\r
99     bool full;\r
100 \r
101     /* Check arguments */\r
102     assert(NULL != handle);\r
103 \r
104     if (USART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))\r
105     {\r
106         full = true;\r
107     }\r
108     else\r
109     {\r
110         full = false;\r
111     }\r
112     return full;\r
113 }\r
114 \r
115 /*!\r
116  * brief Sets up the RX ring buffer.\r
117  *\r
118  * This function sets up the RX ring buffer to a specific USART handle.\r
119  *\r
120  * When the RX ring buffer is used, data received are stored into the ring buffer even when the\r
121  * user doesn't call the USART_TransferReceiveNonBlocking() API. If there is already data received\r
122  * in the ring buffer, the user can get the received data from the ring buffer directly.\r
123  *\r
124  * note When using the RX ring buffer, one byte is reserved for internal use. In other\r
125  * words, if p ringBufferSize is 32, then only 31 bytes are used for saving data.\r
126  *\r
127  * param base USART peripheral base address.\r
128  * param handle USART handle pointer.\r
129  * param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.\r
130  * param ringBufferSize size of the ring buffer.\r
131  */\r
132 void USART_TransferStartRingBuffer(USART_Type *base, usart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)\r
133 {\r
134     /* Check arguments */\r
135     assert(NULL != base);\r
136     assert(NULL != handle);\r
137     assert(NULL != ringBuffer);\r
138 \r
139     /* Setup the ringbuffer address */\r
140     handle->rxRingBuffer     = ringBuffer;\r
141     handle->rxRingBufferSize = ringBufferSize;\r
142     handle->rxRingBufferHead = 0U;\r
143     handle->rxRingBufferTail = 0U;\r
144     /* ring buffer is ready we can start receiving data */\r
145     base->FIFOINTENSET |= USART_FIFOINTENSET_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;\r
146 }\r
147 \r
148 /*!\r
149  * brief Aborts the background transfer and uninstalls the ring buffer.\r
150  *\r
151  * This function aborts the background transfer and uninstalls the ring buffer.\r
152  *\r
153  * param base USART peripheral base address.\r
154  * param handle USART handle pointer.\r
155  */\r
156 void USART_TransferStopRingBuffer(USART_Type *base, usart_handle_t *handle)\r
157 {\r
158     /* Check arguments */\r
159     assert(NULL != base);\r
160     assert(NULL != handle);\r
161 \r
162     if (handle->rxState == (uint8_t)kUSART_RxIdle)\r
163     {\r
164         base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENCLR_RXERR_MASK;\r
165     }\r
166     handle->rxRingBuffer     = NULL;\r
167     handle->rxRingBufferSize = 0U;\r
168     handle->rxRingBufferHead = 0U;\r
169     handle->rxRingBufferTail = 0U;\r
170 }\r
171 \r
172 /*!\r
173  * brief Initializes a USART instance with user configuration structure and peripheral clock.\r
174  *\r
175  * This function configures the USART module with the user-defined settings. The user can configure the configuration\r
176  * structure and also get the default configuration by using the USART_GetDefaultConfig() function.\r
177  * Example below shows how to use this API to configure USART.\r
178  * code\r
179  *  usart_config_t usartConfig;\r
180  *  usartConfig.baudRate_Bps = 115200U;\r
181  *  usartConfig.parityMode = kUSART_ParityDisabled;\r
182  *  usartConfig.stopBitCount = kUSART_OneStopBit;\r
183  *  USART_Init(USART1, &usartConfig, 20000000U);\r
184  * endcode\r
185  *\r
186  * param base USART peripheral base address.\r
187  * param config Pointer to user-defined configuration structure.\r
188  * param srcClock_Hz USART clock source frequency in HZ.\r
189  * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.\r
190  * retval kStatus_InvalidArgument USART base address is not valid\r
191  * retval kStatus_Success Status USART initialize succeed\r
192  */\r
193 status_t USART_Init(USART_Type *base, const usart_config_t *config, uint32_t srcClock_Hz)\r
194 {\r
195     int result;\r
196 \r
197     /* check arguments */\r
198     assert(!((NULL == base) || (NULL == config) || (0U == srcClock_Hz)));\r
199     if ((NULL == base) || (NULL == config) || (0U == srcClock_Hz))\r
200     {\r
201         return kStatus_InvalidArgument;\r
202     }\r
203 \r
204     /* initialize flexcomm to USART mode */\r
205     result = FLEXCOMM_Init(base, FLEXCOMM_PERIPH_USART);\r
206     if (kStatus_Success != result)\r
207     {\r
208         return result;\r
209     }\r
210 \r
211     if (config->enableTx)\r
212     {\r
213         /* empty and enable txFIFO */\r
214         base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK | USART_FIFOCFG_ENABLETX_MASK;\r
215         /* setup trigger level */\r
216         base->FIFOTRIG &= ~(USART_FIFOTRIG_TXLVL_MASK);\r
217         base->FIFOTRIG |= USART_FIFOTRIG_TXLVL(config->txWatermark);\r
218         /* enable trigger interrupt */\r
219         base->FIFOTRIG |= USART_FIFOTRIG_TXLVLENA_MASK;\r
220     }\r
221 \r
222     /* empty and enable rxFIFO */\r
223     if (config->enableRx)\r
224     {\r
225         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK | USART_FIFOCFG_ENABLERX_MASK;\r
226         /* setup trigger level */\r
227         base->FIFOTRIG &= ~(USART_FIFOTRIG_RXLVL_MASK);\r
228         base->FIFOTRIG |= USART_FIFOTRIG_RXLVL(config->rxWatermark);\r
229         /* enable trigger interrupt */\r
230         base->FIFOTRIG |= USART_FIFOTRIG_RXLVLENA_MASK;\r
231     }\r
232     /* setup configuration and enable USART */\r
233     base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |\r
234                 USART_CFG_DATALEN(config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) |\r
235                 USART_CFG_SYNCEN((uint32_t)config->syncMode >> 1) | USART_CFG_SYNCMST((uint8_t)config->syncMode) |\r
236                 USART_CFG_CLKPOL(config->clockPolarity) | USART_CFG_ENABLE_MASK;\r
237 \r
238     /* Setup baudrate */\r
239     result = USART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);\r
240     if (kStatus_Success != result)\r
241     {\r
242         return result;\r
243     }\r
244     /* Setting continuous Clock configuration. used for synchronous mode. */\r
245     USART_EnableContinuousSCLK(base, config->enableContinuousSCLK);\r
246 \r
247     return kStatus_Success;\r
248 }\r
249 \r
250 /*!\r
251  * brief Deinitializes a USART instance.\r
252  *\r
253  * This function waits for TX complete, disables TX and RX, and disables the USART clock.\r
254  *\r
255  * param base USART peripheral base address.\r
256  */\r
257 void USART_Deinit(USART_Type *base)\r
258 {\r
259     /* Check arguments */\r
260     assert(NULL != base);\r
261     while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))\r
262     {\r
263     }\r
264     /* Disable interrupts, disable dma requests, disable peripheral */\r
265     base->FIFOINTENCLR = USART_FIFOINTENCLR_TXERR_MASK | USART_FIFOINTENCLR_RXERR_MASK | USART_FIFOINTENCLR_TXLVL_MASK |\r
266                          USART_FIFOINTENCLR_RXLVL_MASK;\r
267     base->FIFOCFG &= ~(USART_FIFOCFG_DMATX_MASK | USART_FIFOCFG_DMARX_MASK);\r
268     base->CFG &= ~(USART_CFG_ENABLE_MASK);\r
269 }\r
270 \r
271 /*!\r
272  * brief Gets the default configuration structure.\r
273  *\r
274  * This function initializes the USART configuration structure to a default value. The default\r
275  * values are:\r
276  *   usartConfig->baudRate_Bps = 115200U;\r
277  *   usartConfig->parityMode = kUSART_ParityDisabled;\r
278  *   usartConfig->stopBitCount = kUSART_OneStopBit;\r
279  *   usartConfig->bitCountPerChar = kUSART_8BitsPerChar;\r
280  *   usartConfig->loopback = false;\r
281  *   usartConfig->enableTx = false;\r
282  *   usartConfig->enableRx = false;\r
283  *\r
284  * param config Pointer to configuration structure.\r
285  */\r
286 void USART_GetDefaultConfig(usart_config_t *config)\r
287 {\r
288     /* Check arguments */\r
289     assert(NULL != config);\r
290 \r
291     /* Initializes the configure structure to zero. */\r
292     (void)memset(config, 0, sizeof(*config));\r
293 \r
294     /* Set always all members ! */\r
295     config->baudRate_Bps         = 115200U;\r
296     config->parityMode           = kUSART_ParityDisabled;\r
297     config->stopBitCount         = kUSART_OneStopBit;\r
298     config->bitCountPerChar      = kUSART_8BitsPerChar;\r
299     config->loopback             = false;\r
300     config->enableRx             = false;\r
301     config->enableTx             = false;\r
302     config->txWatermark          = kUSART_TxFifo0;\r
303     config->rxWatermark          = kUSART_RxFifo1;\r
304     config->syncMode             = kUSART_SyncModeDisabled;\r
305     config->enableContinuousSCLK = false;\r
306     config->clockPolarity        = kUSART_RxSampleOnFallingEdge;\r
307 }\r
308 \r
309 /*!\r
310  * brief Sets the USART instance baud rate.\r
311  *\r
312  * This function configures the USART module baud rate. This function is used to update\r
313  * the USART module baud rate after the USART module is initialized by the USART_Init.\r
314  * code\r
315  *  USART_SetBaudRate(USART1, 115200U, 20000000U);\r
316  * endcode\r
317  *\r
318  * param base USART peripheral base address.\r
319  * param baudrate_Bps USART baudrate to be set.\r
320  * param srcClock_Hz USART clock source frequency in HZ.\r
321  * retval kStatus_USART_BaudrateNotSupport Baudrate is not support in current clock source.\r
322  * retval kStatus_Success Set baudrate succeed.\r
323  * retval kStatus_InvalidArgument One or more arguments are invalid.\r
324  */\r
325 status_t USART_SetBaudRate(USART_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)\r
326 {\r
327     uint32_t best_diff = (uint32_t)-1, best_osrval = 0xf, best_brgval = (uint32_t)-1;\r
328     uint32_t osrval, brgval, diff, baudrate;\r
329 \r
330     /* check arguments */\r
331     assert(!((NULL == base) || (0 == baudrate_Bps) || (0 == srcClock_Hz)));\r
332     if ((NULL == base) || (0U == baudrate_Bps) || (0U == srcClock_Hz))\r
333     {\r
334         return kStatus_InvalidArgument;\r
335     }\r
336 \r
337     /* If synchronous master mode is enabled, only configure the BRG value. */\r
338     if ((base->CFG & USART_CFG_SYNCEN_MASK) != 0U)\r
339     {\r
340         if ((base->CFG & USART_CFG_SYNCMST_MASK) != 0U)\r
341         {\r
342             brgval    = srcClock_Hz / baudrate_Bps;\r
343             base->BRG = brgval - 1U;\r
344         }\r
345     }\r
346     else\r
347     {\r
348         /*\r
349          * Smaller values of OSR can make the sampling position within a data bit less accurate and may\r
350          * potentially cause more noise errors or incorrect data.\r
351          */\r
352         for (osrval = best_osrval; osrval >= 8U; osrval--)\r
353         {\r
354             brgval = (((srcClock_Hz * 10U) / ((osrval + 1U) * baudrate_Bps)) - 5U) / 10U;\r
355             if (brgval > 0xFFFFU)\r
356             {\r
357                 continue;\r
358             }\r
359             baudrate = srcClock_Hz / ((osrval + 1U) * (brgval + 1U));\r
360             diff     = baudrate_Bps < baudrate ? baudrate - baudrate_Bps : baudrate_Bps - baudrate;\r
361             if (diff < best_diff)\r
362             {\r
363                 best_diff   = diff;\r
364                 best_osrval = osrval;\r
365                 best_brgval = brgval;\r
366             }\r
367         }\r
368 \r
369         /* value over range */\r
370         if (best_brgval > 0xFFFFU)\r
371         {\r
372             return kStatus_USART_BaudrateNotSupport;\r
373         }\r
374 \r
375         base->OSR = best_osrval;\r
376         base->BRG = best_brgval;\r
377     }\r
378 \r
379     return kStatus_Success;\r
380 }\r
381 \r
382 /*!\r
383  * brief Writes to the TX register using a blocking method.\r
384  *\r
385  * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO\r
386  * to have room and writes data to the TX buffer.\r
387  *\r
388  * param base USART peripheral base address.\r
389  * param data Start address of the data to write.\r
390  * param length Size of the data to write.\r
391  */\r
392 void USART_WriteBlocking(USART_Type *base, const uint8_t *data, size_t length)\r
393 {\r
394     /* Check arguments */\r
395     assert(!((NULL == base) || (NULL == data)));\r
396     if ((NULL == base) || (NULL == data))\r
397     {\r
398         return;\r
399     }\r
400     /* Check whether txFIFO is enabled */\r
401     if (0U == (base->FIFOCFG & USART_FIFOCFG_ENABLETX_MASK))\r
402     {\r
403         return;\r
404     }\r
405     for (; length > 0U; length--)\r
406     {\r
407         /* Loop until txFIFO get some space for new data */\r
408         while (0U == (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))\r
409         {\r
410         }\r
411         base->FIFOWR = *data;\r
412         data++;\r
413     }\r
414     /* Wait to finish transfer */\r
415     while (0U == (base->STAT & USART_STAT_TXIDLE_MASK))\r
416     {\r
417     }\r
418 }\r
419 \r
420 /*!\r
421  * brief Read RX data register using a blocking method.\r
422  *\r
423  * This function polls the RX register, waits for the RX register to be full or for RX FIFO to\r
424  * have data and read data from the TX register.\r
425  *\r
426  * param base USART peripheral base address.\r
427  * param data Start address of the buffer to store the received data.\r
428  * param length Size of the buffer.\r
429  * retval kStatus_USART_FramingError Receiver overrun happened while receiving data.\r
430  * retval kStatus_USART_ParityError Noise error happened while receiving data.\r
431  * retval kStatus_USART_NoiseError Framing error happened while receiving data.\r
432  * retval kStatus_USART_RxError Overflow or underflow rxFIFO happened.\r
433  * retval kStatus_Success Successfully received all data.\r
434  */\r
435 status_t USART_ReadBlocking(USART_Type *base, uint8_t *data, size_t length)\r
436 {\r
437     uint32_t statusFlag;\r
438     status_t status = kStatus_Success;\r
439 \r
440     /* check arguments */\r
441     assert(!((NULL == base) || (NULL == data)));\r
442     if ((NULL == base) || (NULL == data))\r
443     {\r
444         return kStatus_InvalidArgument;\r
445     }\r
446 \r
447     /* Check whether rxFIFO is enabled */\r
448     if ((base->FIFOCFG & USART_FIFOCFG_ENABLERX_MASK) == 0U)\r
449     {\r
450         return kStatus_Fail;\r
451     }\r
452     for (; length > 0U; length--)\r
453     {\r
454         /* loop until rxFIFO have some data to read */\r
455         while ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) == 0U)\r
456         {\r
457         }\r
458         /* check rxFIFO statusFlag */\r
459         if ((base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK) != 0U)\r
460         {\r
461             base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;\r
462             base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;\r
463             status = kStatus_USART_RxError;\r
464             break;\r
465         }\r
466         /* check receive statusFlag */\r
467         statusFlag = base->STAT;\r
468         /* Clear all status flags */\r
469         base->STAT |= statusFlag;\r
470         if ((statusFlag & USART_STAT_PARITYERRINT_MASK) != 0U)\r
471         {\r
472             status = kStatus_USART_ParityError;\r
473         }\r
474         if ((statusFlag & USART_STAT_FRAMERRINT_MASK) != 0U)\r
475         {\r
476             status = kStatus_USART_FramingError;\r
477         }\r
478         if ((statusFlag & USART_STAT_RXNOISEINT_MASK) != 0U)\r
479         {\r
480             status = kStatus_USART_NoiseError;\r
481         }\r
482 \r
483         if (kStatus_Success == status)\r
484         {\r
485             *data = (uint8_t)base->FIFORD;\r
486             data++;\r
487         }\r
488         else\r
489         {\r
490             break;\r
491         }\r
492     }\r
493     return status;\r
494 }\r
495 \r
496 /*!\r
497  * brief Initializes the USART handle.\r
498  *\r
499  * This function initializes the USART handle which can be used for other USART\r
500  * transactional APIs. Usually, for a specified USART instance,\r
501  * call this API once to get the initialized handle.\r
502  *\r
503  * param base USART peripheral base address.\r
504  * param handle USART handle pointer.\r
505  * param callback The callback function.\r
506  * param userData The parameter of the callback function.\r
507  */\r
508 status_t USART_TransferCreateHandle(USART_Type *base,\r
509                                     usart_handle_t *handle,\r
510                                     usart_transfer_callback_t callback,\r
511                                     void *userData)\r
512 {\r
513     /* Check 'base' */\r
514     assert(!((NULL == base) || (NULL == handle)));\r
515 \r
516     uint32_t instance = 0;\r
517     usart_to_flexcomm_t handler;\r
518     handler.usart_master_handler = USART_TransferHandleIRQ;\r
519 \r
520     if ((NULL == base) || (NULL == handle))\r
521     {\r
522         return kStatus_InvalidArgument;\r
523     }\r
524 \r
525     instance = USART_GetInstance(base);\r
526 \r
527     (void)memset(handle, 0, sizeof(*handle));\r
528     /* Set the TX/RX state. */\r
529     handle->rxState = (uint8_t)kUSART_RxIdle;\r
530     handle->txState = (uint8_t)kUSART_TxIdle;\r
531     /* Set the callback and user data. */\r
532     handle->callback    = callback;\r
533     handle->userData    = userData;\r
534     handle->rxWatermark = (uint8_t)USART_FIFOTRIG_RXLVL_GET(base);\r
535     handle->txWatermark = (uint8_t)USART_FIFOTRIG_TXLVL_GET(base);\r
536 \r
537     FLEXCOMM_SetIRQHandler(base, handler.flexcomm_handler, handle);\r
538 \r
539     /* Enable interrupt in NVIC. */\r
540     (void)EnableIRQ(s_usartIRQ[instance]);\r
541 \r
542     return kStatus_Success;\r
543 }\r
544 \r
545 /*!\r
546  * brief Transmits a buffer of data using the interrupt method.\r
547  *\r
548  * This function sends data using an interrupt method. This is a non-blocking function, which\r
549  * returns directly without waiting for all data to be written to the TX register. When\r
550  * all data is written to the TX register in the IRQ handler, the USART driver calls the callback\r
551  * function and passes the ref kStatus_USART_TxIdle as status parameter.\r
552  *\r
553  * note The kStatus_USART_TxIdle is passed to the upper layer when all data is written\r
554  * to the TX register. However it does not ensure that all data are sent out. Before disabling the TX,\r
555  * check the kUSART_TransmissionCompleteFlag to ensure that the TX is finished.\r
556  *\r
557  * param base USART peripheral base address.\r
558  * param handle USART handle pointer.\r
559  * param xfer USART transfer structure. See  #usart_transfer_t.\r
560  * retval kStatus_Success Successfully start the data transmission.\r
561  * retval kStatus_USART_TxBusy Previous transmission still not finished, data not all written to TX register yet.\r
562  * retval kStatus_InvalidArgument Invalid argument.\r
563  */\r
564 status_t USART_TransferSendNonBlocking(USART_Type *base, usart_handle_t *handle, usart_transfer_t *xfer)\r
565 {\r
566     /* Check arguments */\r
567     assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));\r
568     if ((NULL == base) || (NULL == handle) || (NULL == xfer))\r
569     {\r
570         return kStatus_InvalidArgument;\r
571     }\r
572     /* Check xfer members */\r
573     assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));\r
574     if ((0U == xfer->dataSize) || (NULL == xfer->data))\r
575     {\r
576         return kStatus_InvalidArgument;\r
577     }\r
578 \r
579     /* Return error if current TX busy. */\r
580     if ((uint8_t)kUSART_TxBusy == handle->txState)\r
581     {\r
582         return kStatus_USART_TxBusy;\r
583     }\r
584     else\r
585     {\r
586         handle->txData        = xfer->data;\r
587         handle->txDataSize    = xfer->dataSize;\r
588         handle->txDataSizeAll = xfer->dataSize;\r
589         handle->txState       = (uint8_t)kUSART_TxBusy;\r
590         /* Enable transmiter interrupt. */\r
591         base->FIFOINTENSET |= USART_FIFOINTENSET_TXLVL_MASK;\r
592     }\r
593     return kStatus_Success;\r
594 }\r
595 \r
596 /*!\r
597  * brief Aborts the interrupt-driven data transmit.\r
598  *\r
599  * This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out\r
600  * how many bytes are still not sent out.\r
601  *\r
602  * param base USART peripheral base address.\r
603  * param handle USART handle pointer.\r
604  */\r
605 void USART_TransferAbortSend(USART_Type *base, usart_handle_t *handle)\r
606 {\r
607     assert(NULL != handle);\r
608 \r
609     /* Disable interrupts */\r
610     USART_DisableInterrupts(base, (uint32_t)kUSART_TxLevelInterruptEnable);\r
611     /* Empty txFIFO */\r
612     base->FIFOCFG |= USART_FIFOCFG_EMPTYTX_MASK;\r
613 \r
614     handle->txDataSize = 0U;\r
615     handle->txState    = (uint8_t)kUSART_TxIdle;\r
616 }\r
617 \r
618 /*!\r
619  * brief Get the number of bytes that have been written to USART TX register.\r
620  *\r
621  * This function gets the number of bytes that have been written to USART TX\r
622  * register by interrupt method.\r
623  *\r
624  * param base USART peripheral base address.\r
625  * param handle USART handle pointer.\r
626  * param count Send bytes count.\r
627  * retval kStatus_NoTransferInProgress No send in progress.\r
628  * retval kStatus_InvalidArgument Parameter is invalid.\r
629  * retval kStatus_Success Get successfully through the parameter \p count;\r
630  */\r
631 status_t USART_TransferGetSendCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)\r
632 {\r
633     assert(NULL != handle);\r
634     assert(NULL != count);\r
635 \r
636     if ((uint8_t)kUSART_TxIdle == handle->txState)\r
637     {\r
638         return kStatus_NoTransferInProgress;\r
639     }\r
640 \r
641     *count = handle->txDataSizeAll - handle->txDataSize;\r
642 \r
643     return kStatus_Success;\r
644 }\r
645 \r
646 /*!\r
647  * brief Receives a buffer of data using an interrupt method.\r
648  *\r
649  * This function receives data using an interrupt method. This is a non-blocking function, which\r
650  *  returns without waiting for all data to be received.\r
651  * If the RX ring buffer is used and not empty, the data in the ring buffer is copied and\r
652  * the parameter p receivedBytes shows how many bytes are copied from the ring buffer.\r
653  * After copying, if the data in the ring buffer is not enough to read, the receive\r
654  * request is saved by the USART driver. When the new data arrives, the receive request\r
655  * is serviced first. When all data is received, the USART driver notifies the upper layer\r
656  * through a callback function and passes the status parameter ref kStatus_USART_RxIdle.\r
657  * For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.\r
658  * The 5 bytes are copied to the xfer->data and this function returns with the\r
659  * parameter p receivedBytes set to 5. For the left 5 bytes, newly arrived data is\r
660  * saved from the xfer->data[5]. When 5 bytes are received, the USART driver notifies the upper layer.\r
661  * If the RX ring buffer is not enabled, this function enables the RX and RX interrupt\r
662  * to receive data to the xfer->data. When all data is received, the upper layer is notified.\r
663  *\r
664  * param base USART peripheral base address.\r
665  * param handle USART handle pointer.\r
666  * param xfer USART transfer structure, see #usart_transfer_t.\r
667  * param receivedBytes Bytes received from the ring buffer directly.\r
668  * retval kStatus_Success Successfully queue the transfer into transmit queue.\r
669  * retval kStatus_USART_RxBusy Previous receive request is not finished.\r
670  * retval kStatus_InvalidArgument Invalid argument.\r
671  */\r
672 status_t USART_TransferReceiveNonBlocking(USART_Type *base,\r
673                                           usart_handle_t *handle,\r
674                                           usart_transfer_t *xfer,\r
675                                           size_t *receivedBytes)\r
676 {\r
677     uint32_t i;\r
678     /* How many bytes to copy from ring buffer to user memory. */\r
679     size_t bytesToCopy = 0U;\r
680     /* How many bytes to receive. */\r
681     size_t bytesToReceive;\r
682     /* How many bytes currently have received. */\r
683     size_t bytesCurrentReceived;\r
684     uint32_t regPrimask = 0U;\r
685 \r
686     /* Check arguments */\r
687     assert(!((NULL == base) || (NULL == handle) || (NULL == xfer)));\r
688     if ((NULL == base) || (NULL == handle) || (NULL == xfer))\r
689     {\r
690         return kStatus_InvalidArgument;\r
691     }\r
692     /* Check xfer members */\r
693     assert(!((0 == xfer->dataSize) || (NULL == xfer->data)));\r
694     if ((0U == xfer->dataSize) || (NULL == xfer->data))\r
695     {\r
696         return kStatus_InvalidArgument;\r
697     }\r
698 \r
699     /* How to get data:\r
700        1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize\r
701           to uart handle, enable interrupt to store received data to xfer->data. When\r
702           all data received, trigger callback.\r
703        2. If RX ring buffer is enabled and not empty, get data from ring buffer first.\r
704           If there are enough data in ring buffer, copy them to xfer->data and return.\r
705           If there are not enough data in ring buffer, copy all of them to xfer->data,\r
706           save the xfer->data remained empty space to uart handle, receive data\r
707           to this empty space and trigger callback when finished. */\r
708     if ((uint8_t)kUSART_RxBusy == handle->rxState)\r
709     {\r
710         return kStatus_USART_RxBusy;\r
711     }\r
712     else\r
713     {\r
714         bytesToReceive       = xfer->dataSize;\r
715         bytesCurrentReceived = 0U;\r
716         /* If RX ring buffer is used. */\r
717         if (handle->rxRingBuffer != NULL)\r
718         {\r
719             /* Disable IRQ, protect ring buffer. */\r
720             regPrimask = DisableGlobalIRQ();\r
721             /* How many bytes in RX ring buffer currently. */\r
722             bytesToCopy = USART_TransferGetRxRingBufferLength(handle);\r
723             if (bytesToCopy != 0U)\r
724             {\r
725                 bytesToCopy = MIN(bytesToReceive, bytesToCopy);\r
726                 bytesToReceive -= bytesToCopy;\r
727                 /* Copy data from ring buffer to user memory. */\r
728                 for (i = 0U; i < bytesToCopy; i++)\r
729                 {\r
730                     xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];\r
731                     /* Wrap to 0. Not use modulo (%) because it might be large and slow. */\r
732                     if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)\r
733                     {\r
734                         handle->rxRingBufferTail = 0U;\r
735                     }\r
736                     else\r
737                     {\r
738                         handle->rxRingBufferTail++;\r
739                     }\r
740                 }\r
741             }\r
742             /* If ring buffer does not have enough data, still need to read more data. */\r
743             if (bytesToReceive != 0U)\r
744             {\r
745                 /* No data in ring buffer, save the request to UART handle. */\r
746                 handle->rxData        = xfer->data + bytesCurrentReceived;\r
747                 handle->rxDataSize    = bytesToReceive;\r
748                 handle->rxDataSizeAll = bytesToReceive;\r
749                 handle->rxState       = (uint8_t)kUSART_RxBusy;\r
750             }\r
751             /* Enable IRQ if previously enabled. */\r
752             EnableGlobalIRQ(regPrimask);\r
753             /* Call user callback since all data are received. */\r
754             if (0U == bytesToReceive)\r
755             {\r
756                 if (handle->callback != NULL)\r
757                 {\r
758                     handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);\r
759                 }\r
760             }\r
761         }\r
762         /* Ring buffer not used. */\r
763         else\r
764         {\r
765             handle->rxData        = xfer->data + bytesCurrentReceived;\r
766             handle->rxDataSize    = bytesToReceive;\r
767             handle->rxDataSizeAll = bytesToReceive;\r
768             handle->rxState       = (uint8_t)kUSART_RxBusy;\r
769 \r
770             /* Enable RX interrupt. */\r
771             base->FIFOINTENSET |= USART_FIFOINTENSET_RXLVL_MASK;\r
772         }\r
773         /* Return the how many bytes have read. */\r
774         if (receivedBytes != NULL)\r
775         {\r
776             *receivedBytes = bytesCurrentReceived;\r
777         }\r
778     }\r
779     return kStatus_Success;\r
780 }\r
781 \r
782 /*!\r
783  * brief Aborts the interrupt-driven data receiving.\r
784  *\r
785  * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out\r
786  * how many bytes not received yet.\r
787  *\r
788  * param base USART peripheral base address.\r
789  * param handle USART handle pointer.\r
790  */\r
791 void USART_TransferAbortReceive(USART_Type *base, usart_handle_t *handle)\r
792 {\r
793     assert(NULL != handle);\r
794 \r
795     /* Only abort the receive to handle->rxData, the RX ring buffer is still working. */\r
796     if (NULL == handle->rxRingBuffer)\r
797     {\r
798         /* Disable interrupts */\r
799         USART_DisableInterrupts(base, (uint32_t)kUSART_RxLevelInterruptEnable);\r
800         /* Empty rxFIFO */\r
801         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;\r
802     }\r
803 \r
804     handle->rxDataSize = 0U;\r
805     handle->rxState    = (uint8_t)kUSART_RxIdle;\r
806 }\r
807 \r
808 /*!\r
809  * brief Get the number of bytes that have been received.\r
810  *\r
811  * This function gets the number of bytes that have been received.\r
812  *\r
813  * param base USART peripheral base address.\r
814  * param handle USART handle pointer.\r
815  * param count Receive bytes count.\r
816  * retval kStatus_NoTransferInProgress No receive in progress.\r
817  * retval kStatus_InvalidArgument Parameter is invalid.\r
818  * retval kStatus_Success Get successfully through the parameter \p count;\r
819  */\r
820 status_t USART_TransferGetReceiveCount(USART_Type *base, usart_handle_t *handle, uint32_t *count)\r
821 {\r
822     assert(NULL != handle);\r
823     assert(NULL != count);\r
824 \r
825     if ((uint8_t)kUSART_RxIdle == handle->rxState)\r
826     {\r
827         return kStatus_NoTransferInProgress;\r
828     }\r
829 \r
830     *count = handle->rxDataSizeAll - handle->rxDataSize;\r
831 \r
832     return kStatus_Success;\r
833 }\r
834 \r
835 /*!\r
836  * brief USART IRQ handle function.\r
837  *\r
838  * This function handles the USART transmit and receive IRQ request.\r
839  *\r
840  * param base USART peripheral base address.\r
841  * param handle USART handle pointer.\r
842  */\r
843 void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)\r
844 {\r
845     /* Check arguments */\r
846     assert((NULL != base) && (NULL != handle));\r
847 \r
848     bool receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));\r
849     bool sendEnabled    = (handle->txDataSize != 0U);\r
850     uint8_t rxdata;\r
851     size_t tmpsize;\r
852 \r
853     /* If RX overrun. */\r
854     if ((base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK) != 0U)\r
855     {\r
856         /* Clear rx error state. */\r
857         base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;\r
858         /* clear rxFIFO */\r
859         base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;\r
860         /* Trigger callback. */\r
861         if (handle->callback != NULL)\r
862         {\r
863             handle->callback(base, handle, kStatus_USART_RxError, handle->userData);\r
864         }\r
865     }\r
866     while ((receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U)) ||\r
867            (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U)))\r
868     {\r
869         /* Receive data */\r
870         if (receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U))\r
871         {\r
872             /* Receive to app bufffer if app buffer is present */\r
873             if (handle->rxDataSize != 0U)\r
874             {\r
875                 rxdata          = (uint8_t)base->FIFORD;\r
876                 *handle->rxData = rxdata;\r
877                 handle->rxDataSize--;\r
878                 handle->rxData++;\r
879                 receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));\r
880                 if (0U == handle->rxDataSize)\r
881                 {\r
882                     if (NULL == handle->rxRingBuffer)\r
883                     {\r
884                         base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;\r
885                     }\r
886                     handle->rxState = (uint8_t)kUSART_RxIdle;\r
887                     if (handle->callback != NULL)\r
888                     {\r
889                         handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);\r
890                     }\r
891                 }\r
892             }\r
893             /* Otherwise receive to ring buffer if ring buffer is present */\r
894             else\r
895             {\r
896                 if (handle->rxRingBuffer != NULL)\r
897                 {\r
898                     /* If RX ring buffer is full, trigger callback to notify over run. */\r
899                     if (USART_TransferIsRxRingBufferFull(handle))\r
900                     {\r
901                         if (handle->callback != NULL)\r
902                         {\r
903                             handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);\r
904                         }\r
905                     }\r
906                     /* If ring buffer is still full after callback function, the oldest data is overridden. */\r
907                     if (USART_TransferIsRxRingBufferFull(handle))\r
908                     {\r
909                         /* Increase handle->rxRingBufferTail to make room for new data. */\r
910                         if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)\r
911                         {\r
912                             handle->rxRingBufferTail = 0U;\r
913                         }\r
914                         else\r
915                         {\r
916                             handle->rxRingBufferTail++;\r
917                         }\r
918                     }\r
919                     /* Read data. */\r
920                     rxdata                                         = (uint8_t)base->FIFORD;\r
921                     handle->rxRingBuffer[handle->rxRingBufferHead] = rxdata;\r
922                     /* Increase handle->rxRingBufferHead. */\r
923                     if ((size_t)handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)\r
924                     {\r
925                         handle->rxRingBufferHead = 0U;\r
926                     }\r
927                     else\r
928                     {\r
929                         handle->rxRingBufferHead++;\r
930                     }\r
931                 }\r
932             }\r
933         }\r
934         /* Send data */\r
935         if (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U))\r
936         {\r
937             base->FIFOWR = *handle->txData;\r
938             handle->txDataSize--;\r
939             handle->txData++;\r
940             sendEnabled = handle->txDataSize != 0U;\r
941             if (!sendEnabled)\r
942             {\r
943                 base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;\r
944                 handle->txState    = (uint8_t)kUSART_TxIdle;\r
945 \r
946                 base->INTENSET |= USART_INTENSET_TXIDLEEN_MASK;\r
947             }\r
948         }\r
949     }\r
950 \r
951     /* Tx idle and the interrupt is enabled. */\r
952     if ((0U != (base->INTENSET & USART_INTENSET_TXIDLEEN_MASK)) &&\r
953         (0U != (base->INTSTAT & USART_INTSTAT_TXIDLE_MASK)) && (handle->txState == (uint8_t)kUSART_TxIdle))\r
954     {\r
955         /* Disable tx idle interrupt */\r
956         base->INTENCLR |= USART_INTENCLR_TXIDLECLR_MASK;\r
957         /* Trigger callback. */\r
958         if (handle->callback != NULL)\r
959         {\r
960             handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);\r
961         }\r
962     }\r
963 \r
964     /* ring buffer is not used */\r
965     if (NULL == handle->rxRingBuffer)\r
966     {\r
967         tmpsize = handle->rxDataSize;\r
968 \r
969         /* restore if rx transfer ends and rxLevel is different from default value */\r
970         if ((tmpsize == 0U) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))\r
971         {\r
972             base->FIFOTRIG =\r
973                 (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);\r
974         }\r
975         /* decrease level if rx transfer is bellow */\r
976         if ((tmpsize != 0U) && (tmpsize < (USART_FIFOTRIG_RXLVL_GET(base) + 1U)))\r
977         {\r
978             base->FIFOTRIG = (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(tmpsize - 1U));\r
979         }\r
980     }\r
981 }\r