From 9c9e48e676864e0d7023d7efa50f5dcc9e196136 Mon Sep 17 00:00:00 2001 From: Theodore Ateba Date: Mon, 12 Feb 2018 20:18:31 +0000 Subject: AVR: Add usart low level driver for ATXMEGA128U4A. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11491 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.c | 483 ++++++++++++++++++++++ os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.h | 448 ++++++++++++++++++++ 2 files changed, 931 insertions(+) create mode 100644 os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.c create mode 100644 os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.h (limited to 'os/hal/ports') diff --git a/os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.c b/os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.c new file mode 100644 index 000000000..10726fafc --- /dev/null +++ b/os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.c @@ -0,0 +1,483 @@ +/* + ChibiOS - Copyright (C) 2016..2018 Theodore Ateba + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_uart_lld.c + * @brief AVR UART subsystem low level driver source. + * + * @addtogroup UART + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) + +/*==========================================================================*/ +/* Driver local definitions. */ +/*==========================================================================*/ + +/*==========================================================================*/ +/* Driver exported variables. */ +/*==========================================================================*/ + +/** + * @brief USART1 (USARTC0) driver identifier. + */ +#if (AVR_UART_USE_USART1 == TRUE) || defined(__DOXYGEN__) +UARTDriver USART1D; +#endif + +/** + * @brief USART2 (USARTC1) driver identifier. + */ +#if (AVR_UART_USE_USART2 == TRUE) || defined(__DOXYGEN__) +UARTDriver USART2D; +#endif + +/** + * @brief USART3 (USARTD0) driver identifier. + */ +#if (AVR_UART_USE_USART3 == TRUE) || defined(__DOXYGEN__) +UARTDriver USART3D; +#endif + +/** + * @brief USART4 (USARTD1) driver identifier. + */ +#if (AVR_UART_USE_USART4 == TRUE) || defined(__DOXYGEN__) +UARTDriver USART4D; +#endif + +/** + * @brief USARTD5 (USARTE0) driver identifier. + */ +#if (AVR_UART_USE_USART5 == TRUE) || defined(__DOXYGEN__) +UARTDriver USART5D; +#endif + +/*==========================================================================*/ +/* Driver local variables and types. */ +/*==========================================================================*/ + +/*==========================================================================*/ +/* Driver local functions. */ +/*==========================================================================*/ + +/** + * @brief Configure the multiprocessor communication mode. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_mpcm(UARTDriver *uartp) { + + if (uartp->config->mpcm) + uartp->usart->CTRLB |= (USART_MPCM_bm); /* Enable the MPCM. */ + else + uartp->usart->CTRLB &= ~(USART_MPCM_bm); /* Disable the MPCM. */ +} + +/** + * @brief Configure the double speed. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_clk2x(UARTDriver *uartp) { + + if (uartp->config->clk2x) + uartp->usart->CTRLB |= (USART_CLK2X_bm); /* Enable double speed. */ + else + uartp->usart->CTRLB &= ~(USART_CLK2X_bm); /* Use normal speed. */ +} + +/** + * @brief Configuration of transmission mode (8/9 bits). + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_txb8(UARTDriver *uartp) { + + if (uartp->config->txb8) + uartp->usart->CTRLB |= (USART_TXB8_bm); /* 9 bits transmission mode. */ + else + uartp->usart->CTRLB &= ~(USART_TXB8_bm); /* 8 bits transmission mode. */ +} + +/** + * @brief Configuration of communication mode. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_cmode(UARTDriver *uartp) { + + if (uartp->config->cmode == USART_CMODE_MSPI) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CMODE_gm) | \ + (USART_CMODE_MSPI_gc); + } + else if (uartp->config->cmode == USART_CMODE_IRCOM) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CMODE_gm) | \ + (USART_CMODE_IRDA_gc); + } + else if (uartp->config->cmode == USART_CMODE_SYNCHRONOUS) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CMODE_gm) | \ + (USART_CMODE_SYNCHRONOUS_gc); + } + else { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CMODE_gm) | \ + (USART_CMODE_ASYNCHRONOUS_gc); + } +} + +/** + * @brief Configuration of the number of stop to use during transmission. + * @details @true set 2 stop bit and @false set 1 stop bit. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_sbmode(UARTDriver *uartp) { + + if (uartp->config->sbmode) { + uartp->usart->CTRLC |= USART_SBMODE_bm; + } + else { + uartp->usart->CTRLC &= ~USART_SBMODE_bm; + } +} + +/** + * @brief Configuration of parity mode. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_pmode(UARTDriver *uartp) { + + if (uartp->config->pmode == USART_PMODE_EVEN) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_PMODE_gm) | \ + (USART_PMODE_EVEN_gc); + } + else if (uartp->config->chsize == USART_PMODE_ODD) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_PMODE_gm) | \ + (USART_PMODE_ODD_gc); + } + else { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_PMODE_gm) | \ + (USART_PMODE_DISABLED_gc); + } +} + +/** + * @brief Configuration of caracter size. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_chsize(UARTDriver *uartp) { + + if (uartp->config->chsize == USART_CHSIZE_5BIT) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CHSIZE_gm) | \ + (USART_CHSIZE_5BIT_gc); + } + else if (uartp->config->chsize == USART_CHSIZE_6BIT) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CHSIZE_gm) | \ + (USART_CHSIZE_6BIT_gc); + } + else if (uartp->config->chsize == USART_CHSIZE_7BIT) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CHSIZE_gm) | \ + (USART_CHSIZE_7BIT_gc); + } + else if (uartp->config->chsize == USART_CHSIZE_8BIT) { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CHSIZE_gm) | \ + (USART_CHSIZE_8BIT_gc); + } + else { + uartp->usart->CTRLC = (uartp->usart->CTRLC & ~USART_CHSIZE_gm) | \ + (USART_CHSIZE_9BIT_gc); + } +} + +/** + * @brief Configuration of the baud rate. + * @note BSCALE is set to 0 for the moment. + * @TODO Support all the BSCALE value + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_cfg_baudrate(UARTDriver *uartp) { + + /* BSCALE = 0. */ + #define BSCALE 0 + uint16_t br = get_bsel(uartp->config->speed); + uartp->usart->BAUDCTRLA =(uint8_t)br; + uartp->usart->BAUDCTRLB =(BSCALE << USART_BSCALE0_bp) | (br >> 8); +} + +/** + * @brief USART de-initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_stop(UARTDriver *uartp) { + + /* Stops RX and TX DMA channels. */ + /* + dmaStreamDisable(uartp->dmarx); + dmaStreamDisable(uartp->dmatx); + */ + + /* Stops USART operations. */ + uartp->usart->CTRLB &= ~(USART_RXEN_bm); /* Disable the USART receiver. */ + uartp->usart->CTRLB &= ~(USART_TXEN_bm); /* Disable the USART transmitter. */ +} + +/** + * @brief USART initialization. + * @details This function must be invoked with interrupts disabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +static void usart_start(UARTDriver *uartp) { + + /* Defensive programming, starting from a clean state. */ + usart_stop(uartp); + + /* Resetting eventual pending status flags. */ + + /* Starting the receiver idle loop. */ + /*uart_enter_rx_idle_loop(uartp);*/ + + usart_cfg_mpcm(uartp); /* Set the multi processor communication mode. */ + usart_cfg_clk2x(uartp); /* Set the USART speed (Normal/Double). */ + usart_cfg_txb8(uartp); /* Set the transmission mode (8/9bits). */ + usart_cfg_cmode(uartp); /* Set the communication mode. */ + usart_cfg_sbmode(uartp);/* Set the stop bit mode. */ + usart_cfg_pmode(uartp); /* Set the parity mode. */ + usart_cfg_chsize(uartp);/* Set the character size. */ + usart_cfg_baudrate(uartp); /* Set the baud rate. */ + uartp->usart->CTRLB |= (USART_RXEN_bm); /* enable the USART receiver. */ + uartp->usart->CTRLB |= (USART_TXEN_bm); /* enable the USART transmitter. */ +} + +/*==========================================================================*/ +/* Driver interrupt handlers. */ +/*==========================================================================*/ + +#if AVR_UART_USE_USART1 || defined(__DOXYGEN__) +/** + * @brief USART1 TX IRQ handler, transmission complete interruption. + * + * @isr + */ +OSAL_IRQ_HANDLER(USARTC0_TXC_vect) { + + OSAL_IRQ_PROLOGUE(); + + /*serve_usart_irq(&UARTD1);*/ + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief USART1 RX IRQ handler, reception complete interruption. + * + * @isr + */ +OSAL_IRQ_HANDLER(USARTC0_RXC_vect) { + + OSAL_IRQ_PROLOGUE(); + + /*serve_usart_irq(&UARTD1);*/ + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief USART1 DRE IRQ handler, data register empty interruption. + * + * @isr + */ +OSAL_IRQ_HANDLER(USARTC0_DRE_vect) { + + OSAL_IRQ_PROLOGUE(); + + /*serve_usart_irq(&UARTD1);*/ + + OSAL_IRQ_EPILOGUE(); +} +#endif /* AVR_UART_USE_USART1 */ + +/*==========================================================================*/ +/* Driver exported functions. */ +/*==========================================================================*/ + +/** + * @brief Low level UART driver initialization. + * + * @notapi + */ +void uart_lld_init(void) { + +#if AVR_UART_USE_USART1 == TRUE + /* Driver initialization. */ + uartObjectInit(&USART1D); + USART1D.usart = &USARTC0; + /*USART1D.usart->CTRLC = 0;*/ + /*USART1D.usart->BAUDCTRLA = 0;*/ +#endif + +#if AVR_UART_USE_USART2 == TRUE + /* Driver initialization. */ + uartObjectInit(&USART2D); +#endif + +#if AVR_UART_USE_USART3 == TRUE + /* Driver initialization. */ + uartObjectInit(&USART3D); +#endif + +#if AVR_UART_USE_USART4 == TRUE + /* Driver initialization. */ + uartObjectInit(&USART4D); +#endif + +#if AVR_UART_USE_USART5 == TRUE + /* Driver initialization. */ + uartObjectInit(&USART5D); +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_start(UARTDriver *uartp) { + + if (uartp->state == UART_STOP) { + /* Enables the peripheral. */ +#if AVR_UART_USE_USART1 == TRUE + if (&USART1D == uartp) { + /* TODO: Implement the DMA part here. */ + } +#endif + } + /* Configures the peripheral. */ + uartp->rxstate = UART_RX_IDLE; + uartp->txstate = UART_TX_IDLE; + usart_start(uartp); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +void uart_lld_stop(UARTDriver *uartp) { + + if (uartp->state == UART_READY) { + /* Resets the peripheral. */ + usart_stop(uartp); + /* Disables the peripheral. */ +#if AVR_UART_USE_USART1 == TRUE + if (&USART1D == uartp) { + /* TODO: Implement the DMA part here. */ + } +#endif + } +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void uart_lld_start_send(UARTDriver *uartp, size_t n, const uint8_t *txbuf) { + + /* TODO: Add support of DMA. */ + while (n--) { + while (!((uartp->usart->STATUS & USART_DREIF_bm) != 0)); + uartp->usart->DATA = *txbuf; + txbuf++; + } +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * + * @notapi + */ +size_t uart_lld_stop_send(UARTDriver *uartp) { + + (void)uartp; + + return 0; +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { + + (void)uartp; + (void)n; + (void)rxbuf; + +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * + * @notapi + */ +size_t uart_lld_stop_receive(UARTDriver *uartp) { + + (void)uartp; + + return 0; +} + +#endif /* HAL_USE_UART == TRUE */ + +/** @} */ diff --git a/os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.h b/os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.h new file mode 100644 index 000000000..9a53a31a7 --- /dev/null +++ b/os/hal/ports/AVR/XMEGA/LLD/USARTv1/hal_uart_lld.h @@ -0,0 +1,448 @@ +/* + ChibiOS - Copyright (C) 2016..2018 Theodore Ateba + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file USARTv1/hal_uart_lld.h + * @brief AVR UART subsystem low level driver header. + * + * @addtogroup UART + * @{ + */ + +#ifndef HAL_UART_LLD_H +#define HAL_UART_LLD_H + +#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) + +/*==========================================================================*/ +/* Driver constants. */ +/*==========================================================================*/ + +/** + * @brief USART communication mode enumerations. + */ +typedef enum { + USART_CMODE_ASYNCHRONOUS = 0x00, /**< USART asynchronous mode. */ + USART_CMODE_SYNCHRONOUS = 0x01, /**< USART synchronous mode. */ + USART_CMODE_IRCOM = 0x10, /**< USART IRCOM mode. */ + USART_CMODE_MSPI = 0x11, /**< USART MSPI mode. */ +} usartcmode_t; + +/** + * @brief USART parity mode enumerations. + */ +typedef enum { + USART_PMODE_DISABLE = 0x00, /**< USART use no parity. */ + USART_PMODE_EVEN = 0x10, /**< USART use even parity. */ + USART_PMODE_ODD = 0x11 /**< USART use odd parity. */ +} usartpmode_t; + +/** + * @brief USART stop bit mode enumerations. + */ +typedef enum { + USART_SBMODE_1BIT = FALSE, /**< USART use 1 stop bit. */ + USART_SBMODE_2BIT = TRUE /**< USART use 2 stop bit. */ +} usartsbmode_t; + +/** + * @brief character size enumerations. + */ +typedef enum { + USART_CHSIZE_5BIT = 0x00, /**< USART use 5 bytes for data. */ + USART_CHSIZE_6BIT = 0x01, /**< USART use 6 bytes for data. */ + USART_CHSIZE_7BIT = 0x02, /**< USART use 7 bytes for data. */ + USART_CHSIZE_8BIT = 0x03, /**< USART use 8 bytes for data. */ + USART_CHSIZE_9BIT = 0x07 /**< USART use 9 bytes for data. */ +} usartchsize_t; + +/*==========================================================================*/ +/* Driver pre-compile time settings. */ +/*==========================================================================*/ + +/** + * @name PLATFORM configuration options + * @{ + */ + +/** + * @brief UART driver on USART1 (USARTC0) enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(AVR_UART_USE_USART1) || defined(__DOXYGEN__) +#define AVR_UART_USE_USART1 FALSE +#endif + +/** + * @brief UART driver on USART2 (USARTC1) enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p FALSE. + */ +#if !defined(AVR_UART_USE_USART2) || defined(__DOXYGEN__) +#define AVR_UART_USE_UART1 FALSE +#endif + +/** + * @brief UART driver on USART3 (USARTD0) enable switch. + * @details If set to @p TRUE the support for USART3 is included. + * @note The default is @p FALSE. + */ +#if !defined(AVR_UART_USE_USART3) || defined(__DOXYGEN__) +#define AVR_UART_USE_USART3 FALSE +#endif + +/** + * @brief UART driver on USART4 (USARTD1) enable switch. + * @details If set to @p TRUE the support for USART4 is included. + * @note The default is @p FALSE. + */ +#if !defined(AVR_UART_USE_USART4) || defined(__DOXYGEN__) +#define AVR_UART_USE_USART4 FALSE +#endif + +/** + * @brief UART driver on USARTE0 enable switch. + * @details If set to @p TRUE the support for USARTE0 is included. + * @note The default is @p FALSE. + */ +#if !defined(AVR_UART_USE_USART5) || defined(__DOXYGEN__) +#define AVR_UART_USE_USART5 FALSE +#endif + +/** + * @brief USART1 (USARTC0) interrupt priority level setting. + */ +#if !defined(AVR_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART1_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART2 (USARTC1) interrupt priority level setting. + */ +#if !defined(AVR_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART2_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART3 (USARTD0) interrupt priority level setting. + */ +#if !defined(AVR_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART3_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART4 (USARTD1) interrupt priority level setting. + */ +#if !defined(AVR_UART_USART4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART4_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART5 (USARTE0) interrupt priority level setting. + */ +#if !defined(AVR_UART_USART5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART5_IRQ_PRIORITY 12 +#endif + +/** + * @brief USART1 (USARTC0) DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(AVR_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART1_DMA_PRIORITY 0 +#endif + +/** + * @brief USART2 (USARTC1) DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(AVR_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART2_DMA_PRIORITY 0 +#endif + +/** + * @brief USART3 (USARTD0) DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(AVR_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART3_DMA_PRIORITY 0 +#endif + +/** + * @brief USART4 (USARTD1) DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(AVR_UART_USART4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART4_DMA_PRIORITY 0 +#endif + +/** + * @brief USART5 (USARTE0) DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA channels but + * because of the channels ordering the RX channel has always priority + * over the TX channel. + */ +#if !defined(AVR_UART_USART5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define AVR_UART_USART5_DMA_PRIORITY 0 +#endif +/** @} */ + +/*==========================================================================*/ +/* Derived constants and error checks. */ +/*==========================================================================*/ + +#if !AVR_UART_USE_USART1 && !AVR_UART_USE_USART2 && \ + !AVR_UART_USE_USART3 && !AVR_UART_USE_USART4 && \ + !AVR_UART_USE_USART5 +#error "UART driver activated but no USART peripheral assigned" +#endif + +/*==========================================================================*/ +/* Driver data structures and types. */ +/*==========================================================================*/ + +/** + * @brief UART driver condition flags type. + */ +typedef uint8_t uartflags_t; + +/** + * @brief Type of structure representing an UART driver. + */ +typedef struct UARTDriver UARTDriver; + +/** + * @brief Generic UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object + */ +typedef void (*uartcb_t)(UARTDriver *uartp); + +/** + * @brief Character received UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object triggering the + * callback + * @param[in] c received character + */ +typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c); + +/** + * @brief Receive error UART notification callback type. + * + * @param[in] uartp pointer to the @p UARTDriver object triggering the + * callback + * @param[in] e receive error mask + */ +typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e); + +/** + * @brief Driver configuration structure. + * @note Implementations may extend this structure to contain more, + * architecture dependent, fields. + */ +typedef struct { + /** + * @brief End of transmission buffer callback. + */ + uartcb_t txend1_cb; + /** + * @brief Physical end of transmission callback. + */ + uartcb_t txend2_cb; + /** + * @brief Receive buffer filled callback. + */ + uartcb_t rxend_cb; + /** + * @brief Character received while out if the @p UART_RECEIVE state. + */ + uartccb_t rxchar_cb; + /** + * @brief Receive error callback. + */ + uartecb_t rxerr_cb; + /* End of tihe mandatory fields. */ + /** + * @brief Bit rate. + */ + uint32_t speed; + /** + * @brief Double transmission speed. + */ + bool clk2x; + /** + * @brief Multiprocessor communication mode bit. + */ + bool mpcm; + /** + * @brief Transmission bit 8. + */ + bool txb8; + /** + * @brief Communication mode. + */ + uint8_t cmode; + /** + * @brief Parity mode. + */ + uint8_t pmode; + /** + * @brief Stop bit mode. + */ + bool sbmode; + /** + * @brief Caractere size. + */ + uint8_t chsize; +} UARTConfig; + +/** + * @brief Structure representing an UART driver. + * @note Implementations may extend this structure to contain more, + * architecture dependent, fields. + */ +struct UARTDriver { + /** + * @brief Driver state. + */ + uartstate_t state; + /** + * @brief Transmitter state. + */ + uarttxstate_t txstate; + /** + * @brief Receiver state. + */ + uartrxstate_t rxstate; + /** + * @brief Current configuration data. + */ + const UARTConfig *config; +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Synchronization flag for transmit operations. + */ + bool early; + /** + * @brief Waiting thread on RX. + */ + thread_reference_t threadrx; + /** + * @brief Waiting thread on TX. + */ + thread_reference_t threadtx; +#endif /* UART_USE_WAIT */ +#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the peripheral. + */ + mutex_t mutex; +#endif /* UART_USE_MUTUAL_EXCLUSION */ +#if defined(UART_DRIVER_EXT_FIELDS) + UART_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields. */ + /** + * @brief Pointer to the USART registers block. + */ + USART_t *usart; + /** + * @brief Clock frequency for the associated USART/UART. + */ + uint32_t clock; + /** + * @brief DMA mode bit mask. + */ + uint32_t dmamode; + /** + * @brief Receive DMA channel. + */ + const DMA_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const DMA_t *dmatx; + /** + * @brief Default receive buffer while into @p UART_RX_IDLE state. + */ + volatile uint16_t rxbuf; +}; + +/*==========================================================================*/ +/* Driver macros. */ +/*==========================================================================*/ + +/** + * @brief This is a macro function to calcul BSEL value according to + * the baudrate selected by the user. + * + * @param[in] baud the baudrate to be configure + */ +#define get_bsel(baud) (F_CPU/(16*baud))-1 + +/*==========================================================================*/ +/* External declarations. */ +/*==========================================================================*/ + +#if (AVR_UART_USE_USART1 == TRUE) && !defined(__DOXYGEN__) +extern UARTDriver USART1D; +#endif + +#if (AVR_UART_USE_USART2 == TRUE) && !defined(__DOXYGEN__) +extern UARTDriver USART2D; +#endif + +#if (AVR_UART_USE_USART3 == TRUE) && !defined(__DOXYGEN__) +extern UARTDriver USART3D; +#endif + +#if (AVR_UART_USE_USART4 == TRUE) && !defined(__DOXYGEN__) +extern UARTDriver USART4D; +#endif + +#if (AVR_UART_USE_USART5 == TRUE) && !defined(__DOXYGEN__) +extern UARTDriver USART5D; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void uart_lld_init(void); + void uart_lld_start(UARTDriver *uartp); + void uart_lld_stop(UARTDriver *uartp); + void uart_lld_start_send(UARTDriver *uartp, size_t n, const uint8_t *txbuf); + size_t uart_lld_stop_send(UARTDriver *uartp); + void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uart_lld_stop_receive(UARTDriver *uartp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_UART == TRUE */ + +#endif /* HAL_UART_LLD_H */ + +/** @} */ -- cgit v1.2.3