From b876b72b395c2acd8652819a0e975b50beaafbfa Mon Sep 17 00:00:00 2001 From: Paul Fleischer Date: Fri, 24 May 2013 20:49:49 +0200 Subject: [PATCH] lm4f: Add control over UART FIFOs --- include/libopencm3/lm4f/uart.h | 86 ++++++++++++++++++++++++++++++++++ lib/lm4f/uart.c | 62 ++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/include/libopencm3/lm4f/uart.h b/include/libopencm3/lm4f/uart.h index 3156b091..967b33ac 100644 --- a/include/libopencm3/lm4f/uart.h +++ b/include/libopencm3/lm4f/uart.h @@ -400,6 +400,41 @@ enum uart_interrupt_flag { UART_INT_RI = UART_IM_RIIM, }; +/** + * \brief UART RX FIFO interrupt trigger levels + * + * The levels indicate how full the FIFO should be before an interrupt is + * generated. UART_FIFO_RX_TRIG_3_4 means that an interrupt is triggered when + * the FIFO is 3/4 full. As the FIFO is 8 elements deep, 1/8 is equal to being + * triggered by a single character. + */ +enum uart_fifo_rx_trigger_level { + UART_FIFO_RX_TRIG_1_8 = UART_IFLS_RXIFLSEL_1_8, + UART_FIFO_RX_TRIG_1_4 = UART_IFLS_RXIFLSEL_1_4, + UART_FIFO_RX_TRIG_1_2 = UART_IFLS_RXIFLSEL_1_2, + UART_FIFO_RX_TRIG_3_4 = UART_IFLS_RXIFLSEL_3_4, + UART_FIFO_RX_TRIG_7_8 = UART_IFLS_RXIFLSEL_7_8 +}; + +/** + * \brief UART TX FIFO interrupt trigger levels + * + * The levels indicate how empty the FIFO should be before an interrupt is + * generated. Note that this indicates the emptiness of the FIFO and not the + * fullness. This is somewhat confusing, but it follows the wording of the + * LM4F120H5QR datasheet. + * + * UART_FIFO_TX_TRIG_3_4 means that an interrupt is triggered when the FIFO is + * 3/4 empty. As the FIFO is 8 elements deep, 7/8 is equal to being triggered + * by a single character. + */ +enum uart_fifo_tx_trigger_level { + UART_FIFO_TX_TRIG_7_8 = UART_IFLS_TXIFLSEL_7_8, + UART_FIFO_TX_TRIG_3_4 = UART_IFLS_TXIFLSEL_3_4, + UART_FIFO_TX_TRIG_1_2 = UART_IFLS_TXIFLSEL_1_2, + UART_FIFO_TX_TRIG_1_4 = UART_IFLS_TXIFLSEL_1_4, + UART_FIFO_TX_TRIG_1_8 = UART_IFLS_TXIFLSEL_1_8 +}; /* ============================================================================= * Function prototypes @@ -429,6 +464,57 @@ void uart_disable_rx_dma(u32 uart); void uart_enable_tx_dma(u32 uart); void uart_disable_tx_dma(u32 uart); +void uart_enable_fifo(u32 uart); +void uart_disable_fifo(u32 uart); +void uart_set_fifo_trigger_levels(u32 uart, + enum uart_fifo_rx_trigger_level rx_level, + enum uart_fifo_tx_trigger_level tx_level); + +/* We inline FIFO full/empty checks as they are intended to be called from ISRs + * */ +/** @ingroup uart_fifo + * @{ + * \brief Determine if the TX fifo is full + * + * @param[in] uart UART block register address base @ref uart_reg_base + */ +static inline +bool uart_is_tx_fifo_full(u32 uart) { + return UART_FR(uart) & UART_FR_TXFF; +} + + +/** + * \brief Determine if the TX fifo is empty + * + * @param[in] uart UART block register address base @ref uart_reg_base + */ +static inline +bool uart_is_tx_fifo_empty(u32 uart) { + return UART_FR(uart) & UART_FR_TXFE; +} + +/** + * \brief Determine if the RX fifo is full + * + * @param[in] uart UART block register address base @ref uart_reg_base + */ +static inline +bool uart_is_rx_fifo_full(u32 uart) { + return UART_FR(uart) & UART_FR_RXFF; +} + +/** + * \brief Determine if the RX fifo is empty + * + * @param[in] uart UART block register address base @ref uart_reg_base + */ +static inline +bool uart_is_rx_fifo_empty(u32 uart) { + return UART_FR(uart) & UART_FR_RXFE; +} +/**@}*/ + void uart_enable_interrupts(u32 uart, enum uart_interrupt_flag ints); void uart_disable_interrupts(u32 uart, enum uart_interrupt_flag ints); void uart_enable_rx_interrupt(u32 uart); diff --git a/lib/lm4f/uart.c b/lib/lm4f/uart.c index 73ccc453..d0ab71bc 100644 --- a/lib/lm4f/uart.c +++ b/lib/lm4f/uart.c @@ -558,6 +558,68 @@ void uart_disable_tx_dma(u32 uart) } /**@}*/ +/** @defgroup uart_fifo UART FIFO control + * @ingroup uart_file + * + * \brief Enabling and controlling UART FIFO + * + * The UART on the LM4F can either be used with a single character TX and RX + * buffer, or with a 8 character TX and RX FIFO. In order to use the FIFO it + * must be enabled, this is done with uart_enable_fifo() and can be disabled + * again with uart_disable_fifo(). On reset the FIFO is disabled, and it must + * be explicitly be enabled. + * + * When enabling the UART FIFOs, RX and TX interrupts are triggered according + * to the amount of data in the FIFOs. For the RX FIFO the trigger level is + * defined by how full the FIFO is. The TX FIFO trigger level is defined by + * how empty the FIFO is instead. + * + * For example, to enable the FIFOs and trigger interrupts for a single + * received and single transmitted character: + * @code{.c} + * uart_enable_fifo(UART0); + * uart_set_fifo_trigger_levels(UART0, UART_FIFO_RX_TRIG_1_8, + * UART_FIFO_TX_TRIG_7_8); + * @endcode + */ +/**@{*/ + +/** + * \brief Enable FIFO for the UART. + * + * @param[in] uart UART block register address base @ref uart_reg_base + */ +void uart_enable_fifo(u32 uart) +{ + UART_LCRH(uart) |= UART_LCRH_FEN; +} + +/** + * \brief Disable FIFO for the UART. + * + * @param[in] uart UART block register address base @ref uart_reg_base + */ +void uart_disable_fifo(u32 uart) +{ + UART_LCRH(uart) &= ~UART_LCRH_FEN; +} + +/** + * \brief Set the FIFO trigger levels. + * + * @param[in] uart UART block register address base @ref uart_reg_base + * @param[in] rx_level Trigger level for RX FIFO + * @param[in] tx_level Trigger level for TX FIFO + */ +void uart_set_fifo_trigger_levels(u32 uart, + enum uart_fifo_rx_trigger_level rx_level, + enum uart_fifo_tx_trigger_level tx_level) +{ + UART_IFLS(uart) = rx_level | tx_level; +} +/**@}*/ + + /** * @} */