blob: ca735e63afa791e37d16994e92d1f7a00621115e [file] [log] [blame]
/*******************************************************************************
* (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.
*
* Core16550 driver implementation. See file "core_16550.h" for a
* description of the functions implemented in this file.
*
* SVN $Revision: 7963 $
* SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $
*/
#include "hal.h"
#include "core_16550.h"
#include "core16550_regs.h"
#include "hal_assert.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* Definitions for transmitter states
*/
#define TX_COMPLETE 0x00U
/*******************************************************************************
* Definition for transmitter FIFO size
*/
#define TX_FIFO_SIZE 16U
/*******************************************************************************
* Default receive interrupt trigger level
*/
#define DEFAULT_RX_TRIG_LEVEL ((uint8_t)UART_16550_FIFO_SINGLE_BYTE)
/*******************************************************************************
* Receiver error status mask and shift offset
*/
#define STATUS_ERROR_MASK ( LSR_OE_MASK | LSR_PE_MASK | \
LSR_FE_MASK | LSR_BI_MASK | LSR_FIER_MASK)
/*******************************************************************************
* Definitions for invalid parameters with proper type
*/
#define INVALID_INTERRUPT 0U
#define INVALID_IRQ_HANDLER ( (uart_16550_irq_handler_t) 0 )
/*******************************************************************************
* Possible values for Interrupt Identification Register Field.
*/
#define IIRF_MODEM_STATUS 0x00U
#define IIRF_THRE 0x02U
#define IIRF_RX_DATA 0x04U
#define IIRF_RX_LINE_STATUS 0x06U
#define IIRF_DATA_TIMEOUT 0x0CU
/*******************************************************************************
* Null parameters with appropriate type definitions
*/
#define NULL_ADDR ( ( addr_t ) 0 )
#define NULL_INSTANCE ( ( uart_16550_instance_t * ) 0 )
#define NULL_BUFF ( ( uint8_t * ) 0 )
/*******************************************************************************
* Possible states for different register bit fields
*/
enum {
DISABLE = 0U,
ENABLE = 1U
};
/*******************************************************************************
* Static function declarations
*/
static void default_tx_handler(uart_16550_instance_t * this_uart);
/*******************************************************************************
* Public function definitions
*/
/***************************************************************************//**
* UART_16550_init.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_init
(
uart_16550_instance_t* this_uart,
addr_t base_addr,
uint16_t baud_value,
uint8_t line_config
)
{
#ifndef NDEBUG
uint8_t dbg1;
uint8_t dbg2;
#endif
uint8_t fifo_config;
uint8_t temp;
HAL_ASSERT( base_addr != NULL_ADDR );
HAL_ASSERT( this_uart != NULL_INSTANCE );
if( ( base_addr != NULL_ADDR ) && ( this_uart != NULL_INSTANCE ) )
{
/* disable interrupts */
HAL_set_8bit_reg(base_addr, IER, DISABLE);
/* reset divisor latch */
HAL_set_8bit_reg_field(base_addr, LCR_DLAB, ENABLE);
#ifndef NDEBUG
dbg1 = HAL_get_8bit_reg_field(base_addr, LCR_DLAB );
HAL_ASSERT( dbg1 == ENABLE );
#endif
/* MSB of baud value */
temp = (uint8_t)(baud_value >> 8);
HAL_set_8bit_reg(base_addr, DMR, temp );
/* LSB of baud value */
HAL_set_8bit_reg(base_addr, DLR, ( (uint8_t)baud_value ) );
#ifndef NDEBUG
dbg1 = HAL_get_8bit_reg(base_addr, DMR );
dbg2 = HAL_get_8bit_reg(base_addr, DLR );
HAL_ASSERT( ( ( ( (uint16_t) dbg1 ) << 8 ) | dbg2 ) == baud_value );
#endif
/* reset divisor latch */
HAL_set_8bit_reg_field(base_addr, LCR_DLAB, DISABLE);
#ifndef NDEBUG
dbg1 = HAL_get_8bit_reg_field(base_addr, LCR_DLAB );
HAL_ASSERT( dbg1 == DISABLE );
#endif
/* set the line control register (bit length, stop bits, parity) */
HAL_set_8bit_reg( base_addr, LCR, line_config );
#ifndef NDEBUG
dbg1 = HAL_get_8bit_reg(base_addr, LCR );
HAL_ASSERT( dbg1 == line_config)
#endif
/* Enable and configure the RX and TX FIFOs. */
fifo_config = ((uint8_t)(DEFAULT_RX_TRIG_LEVEL << FCR_TRIG_LEVEL_SHIFT) |
FCR_RDYN_EN_MASK | FCR_CLEAR_RX_MASK |
FCR_CLEAR_TX_MASK | FCR_ENABLE_MASK );
HAL_set_8bit_reg( base_addr, FCR, fifo_config );
/* disable loopback */
HAL_set_8bit_reg_field( base_addr, MCR_LOOP, DISABLE );
#ifndef NDEBUG
dbg1 = HAL_get_8bit_reg_field(base_addr, MCR_LOOP);
HAL_ASSERT( dbg1 == DISABLE );
#endif
/* Instance setup */
this_uart->base_address = base_addr;
this_uart->tx_buffer = NULL_BUFF;
this_uart->tx_buff_size = TX_COMPLETE;
this_uart->tx_idx = 0U;
this_uart->tx_handler = default_tx_handler;
this_uart->rx_handler = ( (uart_16550_irq_handler_t) 0 );
this_uart->linests_handler = ( (uart_16550_irq_handler_t) 0 );
this_uart->modemsts_handler = ( (uart_16550_irq_handler_t) 0 );
this_uart->status = 0U;
}
}
/***************************************************************************//**
* UART_16550_polled_tx.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_polled_tx
(
uart_16550_instance_t * this_uart,
const uint8_t * pbuff,
uint32_t tx_size
)
{
uint32_t char_idx = 0U;
uint32_t size_sent;
uint8_t status;
HAL_ASSERT( this_uart != NULL_INSTANCE );
HAL_ASSERT( pbuff != NULL_BUFF );
HAL_ASSERT( tx_size > 0U );
if( ( this_uart != NULL_INSTANCE ) &&
( pbuff != NULL_BUFF ) &&
( tx_size > 0U ) )
{
/* Remain in this loop until the entire input buffer
* has been transferred to the UART.
*/
do {
/* Read the Line Status Register and update the sticky record */
status = HAL_get_8bit_reg( this_uart->base_address, LSR );
this_uart->status |= status;
/* Check if TX FIFO is empty. */
if( status & LSR_THRE_MASK )
{
uint32_t fill_size = TX_FIFO_SIZE;
/* Calculate the number of bytes to transmit. */
if ( tx_size < TX_FIFO_SIZE )
{
fill_size = tx_size;
}
/* Fill the TX FIFO with the calculated the number of bytes. */
for ( size_sent = 0U; size_sent < fill_size; ++size_sent )
{
/* Send next character in the buffer. */
HAL_set_8bit_reg( this_uart->base_address, THR,
(uint_fast8_t)pbuff[char_idx++]);
}
/* Calculate the number of untransmitted bytes remaining. */
tx_size -= size_sent;
}
} while ( tx_size );
}
}
/***************************************************************************//**
* UART_16550_polled_tx_string.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_polled_tx_string
(
uart_16550_instance_t * this_uart,
const uint8_t * p_sz_string
)
{
uint32_t char_idx = 0U;
uint32_t fill_size;
uint_fast8_t data_byte;
uint8_t status;
HAL_ASSERT( this_uart != NULL_INSTANCE );
HAL_ASSERT( p_sz_string != NULL_BUFF );
if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFF ) )
{
char_idx = 0U;
/* Get the first data byte from the input buffer */
data_byte = (uint_fast8_t)p_sz_string[char_idx];
/* First check for the NULL terminator byte.
* Then remain in this loop until the entire string in the input buffer
* has been transferred to the UART.
*/
while ( 0U != data_byte )
{
/* Wait until TX FIFO is empty. */
do {
status = HAL_get_8bit_reg( this_uart->base_address,LSR);
this_uart->status |= status;
} while ( !( status & LSR_THRE_MASK ) );
/* Send bytes from the input buffer until the TX FIFO is full
* or we reach the NULL terminator byte.
*/
fill_size = 0U;
while ( (0U != data_byte) && (fill_size < TX_FIFO_SIZE) )
{
/* Send the data byte */
HAL_set_8bit_reg( this_uart->base_address, THR, data_byte );
++fill_size;
char_idx++;
/* Get the next data byte from the input buffer */
data_byte = (uint_fast8_t)p_sz_string[char_idx];
}
}
}
}
/***************************************************************************//**
* UART_16550_irq_tx.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_irq_tx
(
uart_16550_instance_t * this_uart,
const uint8_t * pbuff,
uint32_t tx_size
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( pbuff != NULL_BUFF )
HAL_ASSERT( tx_size > 0U )
if( ( this_uart != NULL_INSTANCE ) &&
( pbuff != NULL_BUFF ) &&
( tx_size > 0U ) )
{
/*Initialize the UART instance with
parameters required for transmission.*/
this_uart->tx_buffer = pbuff;
this_uart->tx_buff_size = tx_size;
/* char_idx; */
this_uart->tx_idx = 0U;
/* assign handler for default data transmission */
this_uart->tx_handler = default_tx_handler;
/* enables TX interrupt */
HAL_set_8bit_reg_field(this_uart->base_address, IER_ETBEI, ENABLE);
}
}
/***************************************************************************//**
* UART_16550_tx_complete.
* See core_16550.h for details of how to use this function.
*/
int8_t
UART_16550_tx_complete
(
uart_16550_instance_t * this_uart
)
{
int8_t returnvalue = 0;
uint8_t status = 0U;
HAL_ASSERT( this_uart != NULL_INSTANCE )
if( this_uart != NULL_INSTANCE )
{
status = HAL_get_8bit_reg(this_uart->base_address,LSR);
this_uart->status |= status;
if( ( this_uart->tx_buff_size == TX_COMPLETE ) &&
( status & LSR_TEMT_MASK ) )
{
returnvalue = (int8_t)1;
}
}
return returnvalue;
}
/***************************************************************************//**
* UART_16550_get_rx.
* See core_16550.h for details of how to use this function.
*/
size_t
UART_16550_get_rx
(
uart_16550_instance_t * this_uart,
uint8_t * rx_buff,
size_t buff_size
)
{
uint8_t status;
size_t rx_size = 0U;
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( rx_buff != (uint8_t *)0 )
HAL_ASSERT( buff_size > 0U )
if( ( this_uart != NULL_INSTANCE ) &&
( rx_buff != (uint8_t *)0 ) &&
( buff_size > 0U ) )
{
status = HAL_get_8bit_reg( this_uart->base_address, LSR );
this_uart->status |= status;
while ( ((status & LSR_DR_MASK) != 0U) && ( rx_size < buff_size ) )
{
rx_buff[rx_size] = HAL_get_8bit_reg( this_uart->base_address, RBR );
rx_size++;
status = HAL_get_8bit_reg( this_uart->base_address, LSR );
this_uart->status |= status;
}
}
return rx_size;
}
/***************************************************************************//**
* UART_16550_isr.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_isr
(
uart_16550_instance_t * this_uart
)
{
uint8_t iirf;
HAL_ASSERT( this_uart != NULL_INSTANCE )
if(this_uart != NULL_INSTANCE )
{
iirf = HAL_get_8bit_reg_field( this_uart->base_address, IIR_IIR );
switch ( iirf )
{
/* Modem status interrupt */
case IIRF_MODEM_STATUS:
{
if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler )
{
HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->modemsts_handler );
if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler )
{
(*(this_uart->modemsts_handler))(this_uart);
}
}
}
break;
/* Transmitter Holding Register Empty interrupt */
case IIRF_THRE:
{
HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->tx_handler );
if ( INVALID_IRQ_HANDLER != this_uart->tx_handler )
{
(*(this_uart->tx_handler))(this_uart);
}
}
break;
/* Received Data Available interrupt */
case IIRF_RX_DATA:
case IIRF_DATA_TIMEOUT:
{
HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->rx_handler );
if ( INVALID_IRQ_HANDLER != this_uart->rx_handler )
{
(*(this_uart->rx_handler))(this_uart);
}
}
break;
/* Line status interrupt */
case IIRF_RX_LINE_STATUS:
{
HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->linests_handler );
if ( INVALID_IRQ_HANDLER != this_uart->linests_handler )
{
(*(this_uart->linests_handler))(this_uart);
}
}
break;
/* Unidentified interrupt */
default:
{
HAL_ASSERT( INVALID_INTERRUPT )
}
}
}
}
/***************************************************************************//**
* UART_16550_set_rx_handler.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_set_rx_handler
(
uart_16550_instance_t * this_uart,
uart_16550_irq_handler_t handler,
uart_16550_rx_trig_level_t trigger_level
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
HAL_ASSERT( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL)
if( ( this_uart != NULL_INSTANCE ) &&
( handler != INVALID_IRQ_HANDLER) &&
( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL) )
{
this_uart->rx_handler = handler;
/* Set the receive interrupt trigger level. */
HAL_set_8bit_reg_field( this_uart->base_address,
FCR_TRIG_LEVEL, trigger_level );
/* Enable receive interrupt. */
HAL_set_8bit_reg_field( this_uart->base_address, IER_ERBFI, ENABLE );
}
}
/***************************************************************************//**
* UART_16550_set_loopback.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_set_loopback
(
uart_16550_instance_t * this_uart,
uart_16550_loopback_t loopback
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE );
HAL_ASSERT( loopback < UART_16550_INVALID_LOOPBACK );
if( ( this_uart != NULL_INSTANCE ) &&
( loopback < UART_16550_INVALID_LOOPBACK ) )
{
if ( loopback == UART_16550_LOOPBACK_OFF )
{
HAL_set_8bit_reg_field( this_uart->base_address,
MCR_LOOP,
DISABLE );
}
else
{
HAL_set_8bit_reg_field( this_uart->base_address,
MCR_LOOP,
ENABLE );
}
}
}
/***************************************************************************//**
* UART_16550_get_rx_status.
* See core_16550.h for details of how to use this function.
*/
uint8_t
UART_16550_get_rx_status
(
uart_16550_instance_t * this_uart
)
{
uint8_t status = UART_16550_INVALID_PARAM;
HAL_ASSERT( this_uart != NULL_INSTANCE );
if( ( this_uart != NULL_INSTANCE ) )
{
/*
* Bit 1 - Overflow error status
* Bit 2 - Parity error status
* Bit 3 - Frame error status
* Bit 4 - Break interrupt indicator
* Bit 7 - FIFO data error status
*/
this_uart->status |= HAL_get_8bit_reg( this_uart->base_address, LSR );
status = ( this_uart->status & STATUS_ERROR_MASK );
/*
* Clear the sticky status for this instance.
*/
this_uart->status = (uint8_t)0;
}
return status;
}
/***************************************************************************//**
* UART_16550_get_modem_status.
* See core_16550.h for details of how to use this function.
*/
uint8_t
UART_16550_get_modem_status
(
uart_16550_instance_t * this_uart
)
{
uint8_t status = UART_16550_NO_ERROR;
HAL_ASSERT( this_uart != NULL_INSTANCE )
if( ( this_uart != NULL_INSTANCE ) )
{
/*
* Extract UART error status and place in lower bits of "status".
* Bit 0 - Delta Clear to Send Indicator
* Bit 1 - Delta Clear to Receive Indicator
* Bit 2 - Trailing edge of Ring Indicator detector
* Bit 3 - Delta Data Carrier Detect indicator
* Bit 4 - Clear To Send
* Bit 5 - Data Set Ready
* Bit 6 - Ring Indicator
* Bit 7 - Data Carrier Detect
*/
status = HAL_get_8bit_reg( this_uart->base_address, MSR );
}
return status;
}
/***************************************************************************//**
* Default TX interrupt handler to automatically transmit data from
* user assgined TX buffer.
*/
static void
default_tx_handler
(
uart_16550_instance_t * this_uart
)
{
uint8_t status;
HAL_ASSERT( NULL_INSTANCE != this_uart )
if ( this_uart != NULL_INSTANCE )
{
HAL_ASSERT( NULL_BUFF != this_uart->tx_buffer )
HAL_ASSERT( 0U != this_uart->tx_buff_size )
if ( ( this_uart->tx_buffer != NULL_BUFF ) &&
( 0U != this_uart->tx_buff_size ) )
{
/* Read the Line Status Register and update the sticky record. */
status = HAL_get_8bit_reg( this_uart->base_address,LSR);
this_uart->status |= status;
/*
* This function should only be called as a result of a THRE interrupt.
* Verify that this is true before proceeding to transmit data.
*/
if ( status & LSR_THRE_MASK )
{
uint32_t size_sent = 0U;
uint32_t fill_size = TX_FIFO_SIZE;
uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;
/* Calculate the number of bytes to transmit. */
if ( tx_remain < TX_FIFO_SIZE )
{
fill_size = tx_remain;
}
/* Fill the TX FIFO with the calculated the number of bytes. */
for ( size_sent = 0U; size_sent < fill_size; ++size_sent )
{
/* Send next character in the buffer. */
HAL_set_8bit_reg( this_uart->base_address, THR,
(uint_fast8_t)this_uart->tx_buffer[this_uart->tx_idx]);
++this_uart->tx_idx;
}
}
/* Flag Tx as complete if all data has been pushed into the Tx FIFO. */
if ( this_uart->tx_idx == this_uart->tx_buff_size )
{
this_uart->tx_buff_size = TX_COMPLETE;
/* disables TX interrupt */
HAL_set_8bit_reg_field( this_uart->base_address,
IER_ETBEI, DISABLE);
}
}
}
}
/***************************************************************************//**
* UART_16550_enable_irq.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_enable_irq
(
uart_16550_instance_t * this_uart,
uint8_t irq_mask
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE )
if( this_uart != NULL_INSTANCE )
{
/* irq_mask encoding: 1- enable
* bit 0 - Receive Data Available Interrupt
* bit 1 - Transmitter Holding Register Empty Interrupt
* bit 2 - Receiver Line Status Interrupt
* bit 3 - Modem Status Interrupt
*/
/* read present interrupts for enabled ones*/
irq_mask |= HAL_get_8bit_reg( this_uart->base_address, IER );
/* Enable interrupts */
HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );
}
}
/***************************************************************************//**
* UART_16550_disable_irq.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_disable_irq
(
uart_16550_instance_t * this_uart,
uint8_t irq_mask
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE )
if( this_uart != NULL_INSTANCE )
{
/* irq_mask encoding: 1 - disable
* bit 0 - Receive Data Available Interrupt
* bit 1 - Transmitter Holding Register Empty Interrupt
* bit 2 - Receiver Line Status Interrupt
* bit 3 - Modem Status Interrupt
*/
/* read present interrupts for enabled ones */
irq_mask = (( (uint8_t)~irq_mask ) &
HAL_get_8bit_reg( this_uart->base_address, IER ));
/* Disable interrupts */
HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );
}
}
/***************************************************************************//**
* UART_16550_set_rxstatus_handler.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_set_rxstatus_handler
(
uart_16550_instance_t * this_uart,
uart_16550_irq_handler_t handler
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
if( ( this_uart != NULL_INSTANCE ) &&
( handler != INVALID_IRQ_HANDLER) )
{
this_uart->linests_handler = handler;
/* Enable receiver line status interrupt. */
HAL_set_8bit_reg_field( this_uart->base_address, IER_ELSI, ENABLE );
}
}
/***************************************************************************//**
* UART_16550_set_tx_handler.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_set_tx_handler
(
uart_16550_instance_t * this_uart,
uart_16550_irq_handler_t handler
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
if( ( this_uart != NULL_INSTANCE ) &&
( handler != INVALID_IRQ_HANDLER) )
{
this_uart->tx_handler = handler;
/* Make TX buffer info invalid */
this_uart->tx_buffer = NULL_BUFF;
this_uart->tx_buff_size = 0U;
/* Enable transmitter holding register Empty interrupt. */
HAL_set_8bit_reg_field( this_uart->base_address, IER_ETBEI, ENABLE );
}
}
/***************************************************************************//**
* UART_16550_set_modemstatus_handler.
* See core_16550.h for details of how to use this function.
*/
void
UART_16550_set_modemstatus_handler
(
uart_16550_instance_t * this_uart,
uart_16550_irq_handler_t handler
)
{
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
if( ( this_uart != NULL_INSTANCE ) &&
( handler != INVALID_IRQ_HANDLER) )
{
this_uart->modemsts_handler = handler;
/* Enable modem status interrupt. */
HAL_set_8bit_reg_field( this_uart->base_address, IER_EDSSI, ENABLE );
}
}
/***************************************************************************//**
* UART_16550_fill_tx_fifo.
* See core_16550.h for details of how to use this function.
*/
size_t
UART_16550_fill_tx_fifo
(
uart_16550_instance_t * this_uart,
const uint8_t * tx_buffer,
size_t tx_size
)
{
uint8_t status;
size_t size_sent = 0U;
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( tx_buffer != NULL_BUFF )
HAL_ASSERT( tx_size > 0U )
/* Fill the UART's Tx FIFO until the FIFO is full or the complete input
* buffer has been written. */
if( (this_uart != NULL_INSTANCE) &&
(tx_buffer != NULL_BUFF) &&
(tx_size > 0U) )
{
/* Read the Line Status Register and update the sticky record. */
status = HAL_get_8bit_reg( this_uart->base_address, LSR );
this_uart->status |= status;
/* Check if TX FIFO is empty. */
if( status & LSR_THRE_MASK )
{
uint32_t fill_size = TX_FIFO_SIZE;
/* Calculate the number of bytes to transmit. */
if ( tx_size < TX_FIFO_SIZE )
{
fill_size = tx_size;
}
/* Fill the TX FIFO with the calculated the number of bytes. */
for ( size_sent = 0U; size_sent < fill_size; ++size_sent )
{
/* Send next character in the buffer. */
HAL_set_8bit_reg( this_uart->base_address, THR,
(uint_fast8_t)tx_buffer[size_sent]);
}
}
}
return size_sent;
}
/***************************************************************************//**
* UART_16550_get_tx_status.
* See core_16550.h for details of how to use this function.
*/
uint8_t
UART_16550_get_tx_status
(
uart_16550_instance_t * this_uart
)
{
uint8_t status = UART_16550_TX_BUSY;
HAL_ASSERT( this_uart != NULL_INSTANCE );
if( ( this_uart != NULL_INSTANCE ) )
{
/* Read the Line Status Register and update the sticky record. */
status = HAL_get_8bit_reg( this_uart->base_address, LSR );
this_uart->status |= status;
/*
* Extract the transmit status bits from the UART's Line Status Register.
* Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty)
* Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty)
*/
status &= ( LSR_THRE_MASK | LSR_TEMT_MASK );
}
return status;
}
#ifdef __cplusplus
}
#endif