]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/peripherals/usart.c
Add SAMA5D2 Xplained IAR demo.
[freertos] / FreeRTOS / Demo / CORTEX_A5_SAMA5D2x_Xplained_IAR / AtmelFiles / drivers / peripherals / usart.c
diff --git a/FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/peripherals/usart.c b/FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/peripherals/usart.c
new file mode 100644 (file)
index 0000000..600a4f2
--- /dev/null
@@ -0,0 +1,825 @@
+/* ----------------------------------------------------------------------------\r
+ *         SAM Software Package License\r
+ * ----------------------------------------------------------------------------\r
+ * Copyright (c) 2015, Atmel Corporation\r
+ *\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the disclaimer below.\r
+ *\r
+ * Atmel's name may not be used to endorse or promote products derived from\r
+ * this software without specific prior written permission.\r
+ *\r
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ * ----------------------------------------------------------------------------\r
+ */\r
+\r
+/** \addtogroup usart_module Working with USART\r
+ * \section Purpose\r
+ * The USART driver provides the interface to configure and use the USART peripheral.\n\r
+ *\r
+ * The USART supports several kinds of communication modes such as full-duplex asynchronous/\r
+ * synchronous serial communication,RS485 with driver control signal,ISO7816,SPI and Test modes.\r
+ *\r
+ * To start a USART transfer with \ref dmad_module "DMA" support, the user could follow these steps:\r
+ * <ul>\r
+ * <li> Configure USART with expected mode and baudrate(see \ref usart_configure), which could be done by:\r
+ * -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li>\r
+ * -# Configuring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li>\r
+ * -# Setting baudrate which is different from mode to mode.\r
+   </li>\r
+ * <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li>\r
+ * <li> Read from or write to the peripheral with  \ref dmad_module </li>\r
+ * </ul>\r
+ *\r
+ * \section Usage\r
+ * <ul>\r
+ * <li>  Enable or disable USART transmitter or receiver using\r
+ * usart_set_transmitter_enabled() and usart_set_receiver_enabled().\r
+ * <li>  Enable or disable USART interrupt using usart_enable_it() or usart_disable_it().\r
+ * </li>\r
+ * </ul>\r
+ *\r
+ * For more accurate information, please look at the USART section of the\r
+ * Datasheet.\r
+ *\r
+ * Related files :\n\r
+ * \ref usart.c\n\r
+ * \ref usart.h\n\r
+*/\r
+\r
+/**\r
+ * \file\r
+ *\r
+ * Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter)\r
+ * controller.\r
+ *\r
+ */\r
+/*-----------------------------------------------------------------------------\r
+*         Headers\r
+ *---------------------------------------------------------------------------*/\r
+\r
+#include "chip.h"\r
+#include "compiler.h"\r
+#include "peripherals/usart.h"\r
+#include "peripherals/pmc.h"\r
+\r
+#include "trace.h"\r
+#include "io.h"\r
+\r
+#include <assert.h>\r
+#include <string.h>\r
+\r
+/*-----------------------------------------------------------------------------\r
+*\r
+ *---------------------------------------------------------------------------*/\r
+\r
+#ifdef CONFIG_HAVE_USART_FIFO\r
+/* Clear FIFO related register if present. Dummy function otherwise. */\r
+static inline void _clear_fifo_control_flags(uint32_t* control_reg)\r
+{\r
+       *control_reg |= US_CR_FIFODIS | US_CR_TXFCLR | US_CR_RXFCLR | US_CR_TXFLCLR;\r
+}\r
+#else\r
+#define _clear_fifo_control_flags(dummy) do {} while(0)\r
+#endif\r
+\r
+/* The CD value scope programmed in MR register. */\r
+#define MIN_CD_VALUE                  0x01\r
+#define MIN_CD_VALUE_SPI              0x04\r
+#define MAX_CD_VALUE                  US_BRGR_CD_Msk\r
+\r
+/* The receiver sampling divide of baudrate clock. */\r
+#define HIGH_FRQ_SAMPLE_DIV           16\r
+#define LOW_FRQ_SAMPLE_DIV            8\r
+\r
+/*----------------------------------------------------------------------------\r
+ *         Exported functions\r
+ *----------------------------------------------------------------------------*/\r
+\r
+/**\r
+ * \brief Reset status bits (PARE, OVER, MANERR, UNRE and PXBRK in US_CSR).\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_reset_status(Usart *usart)\r
+{\r
+       usart->US_CR = US_CR_RSTSTA;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Configures an USART peripheral with the specified parameters.\r
+ *  \param usart  Pointer to the USART peripheral to configure.\r
+ *  \param mode  Desired value for the USART mode register (see the datasheet).\r
+ *  \param baudrate  Baudrate at which the USART should operate (in Hz).\r
+ *  \param clock  Frequency of the system master clock (in Hz).\r
+ */\r
+void usart_configure(Usart *usart, uint32_t mode, uint32_t baudrate)\r
+{\r
+       uint32_t clock = pmc_get_peripheral_clock(get_usart_id_from_addr(usart));\r
+       /* Reset and disable receiver & transmitter */\r
+       uint32_t control = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;\r
+       /* Reset and disable FIFO if present */\r
+       _clear_fifo_control_flags(&control);\r
+       /* apply */\r
+       usart->US_CR = control;\r
+       /* Configure mode */\r
+       usart->US_MR = mode;\r
+\r
+       /* Configure baudrate */\r
+       /* Asynchronous, no oversampling */\r
+       if (((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0)) {\r
+               usart->US_BRGR = (clock / baudrate) / 16;\r
+       }\r
+#ifdef CONFIG_HAVE_USART_SPI_MODE\r
+       if (((mode & US_MR_USART_MODE_SPI_MASTER) ==\r
+            US_MR_USART_MODE_SPI_MASTER) || ((mode & US_MR_SYNC) == US_MR_SYNC)) {\r
+               if ((mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) {\r
+                       usart->US_BRGR = clock / baudrate;\r
+               } else {\r
+                       if ((mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV) {\r
+                               usart->US_BRGR = clock / baudrate / 8;\r
+                       }\r
+               }\r
+       }\r
+#endif /* CONFIG_HAVE_USART_SPI_MODE */\r
+\r
+       /* TODO other modes */\r
+\r
+       /* Disable all interrupts */\r
+       usart->US_IDR = 0xFFFFFFFF;\r
+       /* Enable receiver and transmitter */\r
+       usart->US_CR = US_CR_RXEN | US_CR_TXEN;\r
+}\r
+\r
+/**\r
+ * \brief   Get present status\r
+ * \param usart  Pointer to an USART peripheral.\r
+ */\r
+uint32_t usart_get_status(Usart *usart)\r
+{\r
+       return usart->US_CSR;\r
+}\r
+\r
+/**\r
+ * \brief   Enable interrupt\r
+ * \param usart  Pointer to an USART peripheral.\r
+ * \param mode  Interrupt mode.\r
+ */\r
+void usart_enable_it(Usart *usart, uint32_t mode)\r
+{\r
+       usart->US_IER = mode;\r
+}\r
+\r
+/**\r
+ * \brief   Disable interrupt\r
+ * \param usart  Pointer to an USART peripheral.\r
+ * \param mode  Interrupt mode.\r
+ */\r
+void usart_disable_it(Usart *usart, uint32_t mode)\r
+{\r
+       usart->US_IDR = mode;\r
+}\r
+\r
+/**\r
+ * \brief   Return interrupt mask\r
+ * \param usart  Pointer to an USART peripheral.\r
+ */\r
+uint32_t usart_get_it_mask(Usart *usart)\r
+{\r
+       return usart->US_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Enables or disables the transmitter of an USART peripheral.\r
+ * \param usart  Pointer to an USART peripheral\r
+ * \param enabled  If true, the transmitter is enabled; otherwise it is\r
+ *                disabled.\r
+ */\r
+void usart_set_transmitter_enabled(Usart *usart, uint8_t enabled)\r
+{\r
+       if (enabled) {\r
+               usart->US_CR = US_CR_TXEN;\r
+       } else {\r
+               usart->US_CR = US_CR_TXDIS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enables or disables the receiver of an USART peripheral\r
+ * \param usart  Pointer to an USART peripheral\r
+ * \param enabled  If true, the receiver is enabled; otherwise it is disabled.\r
+ */\r
+void usart_set_receiver_enabled(Usart *usart, uint8_t enabled)\r
+{\r
+       if (enabled) {\r
+               usart->US_CR = US_CR_RXEN;\r
+       } else {\r
+               usart->US_CR = US_CR_RXDIS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enables or disables the Request To Send (RTS) of an USART peripheral\r
+ * \param usart  Pointer to an USART peripheral\r
+ * \param enabled  If true, the RTS is enabled (0); otherwise it is disabled.\r
+ */\r
+void usart_set_rts_enabled(Usart *usart, uint8_t enabled)\r
+{\r
+       if (enabled) {\r
+               usart->US_CR = US_CR_RTSEN;\r
+       } else {\r
+               usart->US_CR = US_CR_RTSDIS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Immediately stop and disable USART transmitter.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_reset_tx(Usart *usart)\r
+{\r
+       /* Reset transmitter */\r
+       usart->US_CR = US_CR_RSTTX | US_CR_TXDIS;\r
+}\r
+\r
+/**\r
+ * \brief Configure the transmit timeguard register.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ * \param timeguard The value of transmit timeguard.\r
+ */\r
+void usart_set_tx_timeguard(Usart *usart, uint32_t timeguard)\r
+{\r
+       usart->US_TTGR = timeguard;\r
+}\r
+\r
+/**\r
+ * \brief Immediately stop and disable USART receiver.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_reset_rx(Usart *usart)\r
+{\r
+       /* Reset Receiver */\r
+       usart->US_CR = US_CR_RSTRX | US_CR_RXDIS;\r
+}\r
+\r
+/**\r
+ * \brief Configure the receive timeout register.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ * \param timeout The value of receive timeout.\r
+ */\r
+void usart_set_rx_timeout(Usart *usart, uint32_t timeout)\r
+{\r
+       usart->US_RTOR = timeout;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Start transmission of a break.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_start_tx_break(Usart *usart)\r
+{\r
+       usart->US_CR = US_CR_STTBRK;\r
+}\r
+\r
+/**\r
+ * \brief Stop transmission of a break.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_stop_tx_break(Usart *usart)\r
+{\r
+       usart->US_CR = US_CR_STPBRK;\r
+}\r
+\r
+/**\r
+ * \brief Start waiting for a character before clocking the timeout count.\r
+ * Reset the status bit TIMEOUT in US_CSR.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_start_rx_timeout(Usart *usart)\r
+{\r
+       usart->US_CR = US_CR_STTTO;\r
+}\r
+\r
+/**\r
+ * \brief Reset the ITERATION in US_CSR when the ISO7816 mode is enabled.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_reset_iterations(Usart *usart)\r
+{\r
+       usart->US_CR = US_CR_RSTIT;\r
+}\r
+\r
+/**\r
+ * \brief Reset NACK in US_CSR.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_reset_nack(Usart *usart)\r
+{\r
+       usart->US_CR = US_CR_RSTNACK;\r
+}\r
+\r
+/**\r
+ * \brief Restart the receive timeout.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_restart_rx_timeout(Usart *usart)\r
+{\r
+       usart->US_CR = US_CR_RETTO;\r
+}\r
+\r
+/**\r
+ * \brief Sends one packet of data through the specified USART peripheral. This\r
+ * function operates synchronously, so it only returns when the data has been\r
+ * actually sent.\r
+ * \param usart  Pointer to an USART peripheral.\r
+ * \param data  Data to send including 9nth bit and sync field if necessary (in\r
+ *        the same format as the US_THR register in the datasheet).\r
+ * \param timeout  Time out value (0 = no timeout).\r
+ */\r
+void usart_write(Usart *usart, uint16_t data, volatile uint32_t timeout)\r
+{\r
+       if (timeout == 0) {\r
+               while ((usart->US_CSR & US_CSR_TXRDY) == 0) ;\r
+       } else {\r
+               while ((usart->US_CSR & US_CSR_TXRDY) == 0) {\r
+                       if (timeout == 0) {\r
+                               trace_error("usart_write: Timed out.\n\r");\r
+                               return;\r
+                       }\r
+                       timeout--;\r
+               }\r
+       }\r
+       usart->US_THR = data;\r
+}\r
+\r
+/**\r
+ * \brief  Reads and return a packet of data on the specified USART peripheral. This\r
+ * function operates asynchronously, so it waits until some data has been\r
+ * received.\r
+ * \param usart  Pointer to an USART peripheral.\r
+ * \param timeout  Time out value (0 -> no timeout).\r
+ */\r
+uint16_t usart_read(Usart *usart, volatile uint32_t timeout)\r
+{\r
+       if (timeout == 0) {\r
+               while ((usart->US_CSR & US_CSR_RXRDY) == 0) ;\r
+       } else {\r
+               while ((usart->US_CSR & US_CSR_RXRDY) == 0) {\r
+                       if (timeout == 0) {\r
+                               trace_error("usart_read: Timed out.\n\r");\r
+                               return 0;\r
+                       }\r
+                       timeout--;\r
+               }\r
+       }\r
+       return usart->US_RHR;\r
+}\r
+\r
+/**\r
+ * \brief  Returns 1 if some data has been received and can be read from an USART;\r
+ * otherwise returns 0.\r
+ * \param usart  Pointer to an USART instance.\r
+ */\r
+uint8_t usart_is_data_available(Usart *usart)\r
+{\r
+       if ((usart->US_CSR & US_CSR_RXRDY) != 0) {\r
+               return 1;\r
+       } else {\r
+               return 0;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief   Return 1 if a character can be read in USART\r
+ * \param usart  Pointer to an USART peripheral.\r
+ */\r
+uint32_t usart_is_rx_ready(Usart *usart)\r
+{\r
+       return (usart->US_CSR & US_CSR_RXRDY);\r
+}\r
+\r
+/**\r
+ * \brief   Return 1 if a character send in USART\r
+ * \param usart  Pointer to an USART peripheral.\r
+ */\r
+uint32_t usart_is_tx_ready(Usart *usart)\r
+{\r
+       return (usart->US_CSR & US_CSR_TXRDY);\r
+}\r
+\r
+/**\r
+ * \brief  Sends one packet of data through the specified USART peripheral. This\r
+ * function operates synchronously, so it only returns when the data has been\r
+ * actually sent.\r
+ * \param usart  Pointer to an USART peripheral.\r
+ * \param c  Character to send\r
+ */\r
+void usart_put_char(Usart *usart, uint8_t c)\r
+{\r
+       /* Wait for the transmitter to be ready */\r
+       while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) ;\r
+       /* Send character */\r
+       /* Force an octet write to avoid race conditions with FIFO mode */\r
+       writeb(&usart->US_THR, c);\r
+}\r
+\r
+/**\r
+ * \brief  Reads and returns a character from the USART.\r
+ * \note This function is synchronous (i.e. uses polling).\r
+ * \param usart  Pointer to an USART peripheral.\r
+ * \return Character received.\r
+ */\r
+uint8_t usart_get_char(Usart *usart)\r
+{\r
+       while ((usart->US_CSR & US_CSR_RXRDY) == 0) ;\r
+       /* Force an octet read to avoid race conditions with FIFO mode */\r
+       uint8_t v;\r
+       readb(&usart->US_RHR, &v);\r
+       return v;\r
+}\r
+\r
+/**\r
+ * \brief  Sets the filter value for the IRDA demodulator.\r
+ * \param usart  Pointer to an USART instance.\r
+ * \param filter  Filter value.\r
+ */\r
+void usart_set_irda_filter(Usart *usart, uint8_t filter)\r
+{\r
+       assert(usart != NULL);\r
+\r
+       usart->US_IF = filter;\r
+       /* Set IrDA mode. */\r
+       usart->US_MR = (usart->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_IRDA;\r
+}\r
+\r
+/**\r
+ * \brief Select the SCK pin as the source of baud rate for the USART\r
+ * synchronous slave modes.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_set_sync_slave_baudrate(Usart *usart)\r
+{\r
+       usart->US_MR = (usart->US_MR & ~US_MR_USCLKS_Msk) | US_MR_USCLKS_SCK | US_MR_SYNC;\r
+}\r
+\r
+/**\r
+ * \brief Calculate a clock divider (\e CD) for the USART SPI master mode to\r
+ * generate a baud rate as close as possible to the baud rate set point.\r
+ *\r
+ * \note Baud rate calculation:\r
+ * \f$ Baudrate = \frac{SelectedClock}{CD} \f$.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ * \param baudrate Baud rate set point.\r
+ *\r
+ * \retval 0 Baud rate is successfully initialized.\r
+ * \retval 1 Baud rate set point is out of range for the given input clock\r
+ * frequency.\r
+ */\r
+uint32_t usart_set_spi_master_baudrate(Usart *usart, uint32_t baudrate)\r
+{\r
+       uint32_t cd;\r
+       uint32_t clock = pmc_get_peripheral_clock(get_usart_id_from_addr(usart));\r
+\r
+       /* Calculate the clock divider according to the formula in SPI mode. */\r
+       cd = (clock + baudrate / 2) / baudrate;\r
+       if (cd < MIN_CD_VALUE_SPI || cd > MAX_CD_VALUE) {\r
+               return 1;\r
+       }\r
+       usart->US_BRGR = cd << US_BRGR_CD_Pos;\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \brief Select the SCK pin as the source of baudrate for the USART SPI slave\r
+ * mode.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ */\r
+void usart_set_spi_slave_baudrate(Usart *usart)\r
+{\r
+       usart->US_MR &= ~US_MR_USCLKS_Msk;\r
+       usart->US_MR |= US_MR_USCLKS_SCK;\r
+}\r
+\r
+/**\r
+ * \brief Configure USART to work in hardware handshaking mode.\r
+ *\r
+ * \note By default, the transmitter and receiver aren't enabled.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ *\r
+ * \retval 0 on success.\r
+ * \retval 1 on failure.\r
+ */\r
+uint32_t usart_init_hw_handshaking(Usart *usart)\r
+{\r
+       /* The USART should be initialized first as standard RS232. */\r
+       /* Set hardware handshaking mode. */\r
+       usart->US_MR = (usart->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_HW_HANDSHAKING;\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \brief Calculate a clock divider(CD) and a fractional part (FP) for the\r
+ * USART asynchronous modes to generate a baudrate as close as possible to\r
+ * the baudrate set point.\r
+ *\r
+ * \note Baud rate calculation: Baudrate = mck/(Over * (CD + FP/8))\r
+ * (Over being 16 or 8). The maximal oversampling is selected if it allows to\r
+ * generate a baudrate close to the set point.\r
+ *\r
+ * \param usart Pointer to a USART instance.\r
+ * \param baudrate Baud rate set point.\r
+ *\r
+ * \retval 0 Baud rate is successfully initialized.\r
+ * \retval 1 Baud rate set point is out of range for the given input clock\r
+ * frequency.\r
+ */\r
+uint32_t usart_set_async_baudrate(Usart *usart, uint32_t baudrate)\r
+{\r
+       uint32_t over, cd_fp, cd, fp;\r
+       uint32_t mck;\r
+\r
+       /* get peripheral clock */\r
+       mck = pmc_get_peripheral_clock(get_usart_id_from_addr(usart));\r
+\r
+       /* Calculate the receiver sampling divide of baudrate clock. */\r
+       if (mck >= HIGH_FRQ_SAMPLE_DIV * baudrate) {\r
+               over = HIGH_FRQ_SAMPLE_DIV;\r
+       } else {\r
+               over = LOW_FRQ_SAMPLE_DIV;\r
+       }\r
+\r
+       /* Calculate clock divider according to the fraction calculated formula. */\r
+       cd_fp = (8 * mck + (over * baudrate) / 2) / (over * baudrate);\r
+       cd = cd_fp >> 0x03;\r
+       fp = cd_fp & 0x07;\r
+       if (cd < MIN_CD_VALUE || cd > MAX_CD_VALUE) {\r
+               return 1;\r
+       }\r
+\r
+       /* Configure the OVER bit in MR register. */\r
+       if (over == 8) {\r
+               usart->US_MR |= US_MR_OVER;\r
+       }\r
+\r
+       /* Configure the baudrate generate register. */\r
+       usart->US_BRGR = (cd << US_BRGR_CD_Pos) | (fp << US_BRGR_FP_Pos);\r
+\r
+       return 0;\r
+}\r
+\r
+/*-----------------------------------------------------------------------------\r
+*        Functions if FIFO are used\r
+ *---------------------------------------------------------------------------*/\r
+\r
+#ifdef CONFIG_HAVE_USART_FIFO\r
+/**\r
+ * \brief Configure the FIFO of USART device\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \param tx_thres\r
+ * \param rx_down_thres\r
+ * \param rx_up_thres\r
+ * \param ready_modes\r
+ */\r
+void usart_fifo_configure(Usart *usart, uint8_t tx_thres,\r
+                         uint8_t rx_down_thres, uint8_t rx_up_thres,\r
+                         uint32_t ready_modes)\r
+{\r
+       /* Disable transmitter & receiver */\r
+       usart->US_CR = US_CR_RXDIS | US_CR_TXDIS;\r
+       /* Enable FIFO */\r
+       usart->US_CR = US_CR_FIFOEN;\r
+       /* Configure FIFO */\r
+       usart->US_FMR = US_FMR_TXFTHRES(tx_thres) | US_FMR_RXFTHRES(rx_down_thres)\r
+               | US_FMR_RXFTHRES2(rx_up_thres) | ready_modes;\r
+\r
+       /* Disable all fifo related interrupts */\r
+       usart->US_FIDR = 0xFFFFFFFF;\r
+\r
+       /* Reenable receiver & transmitter */\r
+       usart->US_CR = US_CR_RXEN | US_CR_TXEN;\r
+}\r
+\r
+/**\r
+ * \brief Disable the FIFO mode from the USART device\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \note receiver and transmitter are reenabled.\r
+ */\r
+void usart_fifo_disable(Usart *usart)\r
+{\r
+       /* Reset and disable receiver & transmitter */\r
+       uint32_t control = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;\r
+       /* clear and disable FIFO */\r
+       _clear_fifo_control_flags(&control);\r
+       /* apply */\r
+       usart->US_CR = control;\r
+\r
+       /* Reenable receiver & transmitter */\r
+       usart->US_CR = US_CR_RXEN | US_CR_TXEN;\r
+}\r
+\r
+/**\r
+ * \brief Enable FIFO related interrupts according to the given mask\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \param interrupt_mask The mask to apply\r
+ */\r
+void usart_fifo_enable_it(Usart *usart, uint32_t interrupt_mask)\r
+{\r
+       usart->US_FIER = interrupt_mask;\r
+}\r
+\r
+/**\r
+ * \brief Disable FIFO related interrupts according to the given mask\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \param interrupt_mask The mask to apply\r
+ */\r
+void usart_fifo_disable_it(Usart *usart, uint32_t interrupt_mask)\r
+{\r
+       usart->US_FIDR = interrupt_mask;\r
+}\r
+\r
+/**\r
+ * \brief Retrive FIFO related interrupt mask.\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \return current FIFO interrupt mask.\r
+ */\r
+uint32_t usart_fifo_get_interrupts(Usart *usart)\r
+{\r
+       return usart->US_FIMR;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Get the size occupied in the input FIFO of USART device.\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \return Size occupied in the input FIFO (not read yet) in octet\r
+ */\r
+uint32_t usart_fifo_rx_size(Usart *usart)\r
+{\r
+       return (usart->US_FLR & US_FLR_RXFL_Msk) >> US_FLR_RXFL_Pos;\r
+}\r
+\r
+/**\r
+ * \brief Get the size occupied in the ouput FIFO of USART device.\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \return Size occupied in the output FIFO (not sent yet) in octet\r
+ */\r
+uint32_t usart_fifo_tx_size(Usart *usart)\r
+{\r
+       return (usart->US_FLR & US_FLR_TXFL_Msk) >> US_FLR_TXFL_Pos;\r
+}\r
+\r
+/**\r
+ * \brief Reads from USART device input channel until the specified length is\r
+ * reached.\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \param stream Pointer to the receive buffer.\r
+ * \param len Size of the receive buffer, in octets.\r
+ *\r
+ * \return Number of read octets\r
+ *\r
+ * \warning WORKS ONLY IN LITTLE ENDIAN MODE!\r
+ *\r
+ * \note The FIFO must be configured before using this function.\r
+ * \note In case of a TIMEOUT or a BREAK, a null character is appended to the\r
+ * buffer and the returned value should be inferior to \ref len.\r
+ */\r
+uint32_t usart_read_stream(Usart *usart, void *stream, uint32_t len)\r
+{\r
+       uint8_t* buffer = stream;\r
+       uint32_t left = len;\r
+       while (left > 0) {\r
+               /* Stop reception if a timeout or break occur */\r
+               if ((usart->US_CSR & (US_CSR_TIMEOUT | US_CSR_RXBRK)) != 0) {\r
+                       *buffer = '\0';\r
+                       break;\r
+               }\r
+\r
+               if ((usart->US_CSR & US_CSR_RXRDY) == 0) continue;\r
+\r
+               /* Get FIFO size (in octets) and clamp it */\r
+               uint32_t buf_size = usart_fifo_rx_size(usart);\r
+               buf_size = buf_size > left ? left : buf_size;\r
+\r
+               /* Fill the buffer as must as possible with four data reads */\r
+               while (buf_size >= sizeof(uint32_t)) {\r
+                       *(uint32_t*)buffer = usart->US_RHR;\r
+                       buffer += sizeof(uint32_t);\r
+                       left -= sizeof(uint32_t);\r
+                       buf_size -= sizeof(uint32_t);\r
+               }\r
+               /* Add tail data if stream is not 4 octet aligned */\r
+               if (buf_size >= sizeof(uint16_t)) {\r
+                       /* two data read */\r
+                       readhw(&usart->US_RHR, (uint16_t*)buffer);\r
+                       left -= sizeof(uint16_t);\r
+                       buffer += sizeof(uint16_t);\r
+                       buf_size -= sizeof(uint16_t);\r
+               }\r
+               if (buf_size >= sizeof(uint8_t)) {\r
+                       /* one data read */\r
+                       readb(&usart->US_RHR, buffer);\r
+                       buffer += sizeof(uint8_t);\r
+                       left -= sizeof(uint8_t);\r
+                       buf_size -= sizeof(uint8_t);\r
+               }\r
+       }\r
+       return len - left;\r
+}\r
+\r
+/**\r
+ * \brief Writes given data to USART device output channel until the specified\r
+ * length is reached.\r
+ *\r
+ * \param usart Pointer to an USART instance.\r
+ * \param stream Pointer to the data to send.\r
+ * \param len Size of the data to send, in octets.\r
+ *\r
+ * \return Number of written octets\r
+ *\r
+ * \warning WORKS ONLY IN LITTLE ENDIAN MODE!\r
+ *\r
+ * \note The FIFO must be configured before using this function.\r
+ * \note This function do not wait for the FIFO to be empty.\r
+ * \note In case of a TIMEOUT the transmission is aborted and the returned value\r
+ * should be inferior to \ref len.\r
+ */\r
+uint32_t usart_write_stream(Usart *usart, const void *stream, uint32_t len)\r
+{\r
+       const uint8_t* buffer = stream;\r
+       uint32_t left = len;\r
+       int32_t fifo_size = get_peripheral_fifo_depth(usart);\r
+       if (fifo_size < 0)\r
+               return 0;\r
+\r
+       while (left > 0) {\r
+               if ((usart->US_CSR & US_CSR_TXRDY) == 0) continue;\r
+\r
+               /* Get FIFO free size (int octet) and clamp it */\r
+               uint32_t buf_size = fifo_size - usart_fifo_tx_size(usart);\r
+               buf_size = buf_size > left ? left : buf_size;\r
+\r
+               /* Fill the FIFO as must as possible with four data writes */\r
+               while (buf_size >= sizeof(uint32_t)) {\r
+                       usart->US_THR = *(uint32_t*)buffer;\r
+                       buffer += sizeof(uint32_t);\r
+                       left -= sizeof(uint32_t);\r
+                       buf_size -= sizeof(uint32_t);\r
+               }\r
+               /* Add tail data if stream is not 4 octet aligned */\r
+               if (buf_size >= sizeof(uint16_t)) {\r
+                       /* two data write */\r
+                       writehw(&usart->US_THR, *(uint16_t*)buffer);\r
+                       buffer += sizeof(uint16_t);\r
+                       left -= sizeof(uint16_t);\r
+                       buf_size -= sizeof(uint16_t);\r
+               }\r
+               if (buf_size >= sizeof(uint8_t)) {\r
+                       /* one data write */\r
+                       writeb(&usart->US_THR, *buffer);\r
+                       buffer += sizeof(uint8_t);\r
+                       left -= sizeof(uint8_t);\r
+                       buf_size -= sizeof(uint8_t);\r
+               }\r
+       }\r
+       return len - left;\r
+}\r
+\r
+#endif\r