blob: b4f40dc1e0da3f5f6b0b16ae81d420568f024986 [file] [log] [blame]
/*******************************************************************************
* (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.
*
* CoreUARTapb driver implementation. See file "core_uart_apb.h" for a
* description of the functions implemented in this file.
*
* SVN $Revision: 9082 $
* SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $
*/
#include "hal.h"
#include "coreuartapb_regs.h"
#include "core_uart_apb.h"
#include "hal_assert.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NULL_INSTANCE ( ( UART_instance_t* ) 0 )
#define NULL_BUFFER ( ( uint8_t* ) 0 )
#define MAX_LINE_CONFIG ( ( uint8_t )( DATA_8_BITS | ODD_PARITY ) )
#define MAX_BAUD_VALUE ( ( uint16_t )( 0x1FFF ) )
#define STATUS_ERROR_MASK ( ( uint8_t )( STATUS_PARITYERR_MASK | \
STATUS_OVERFLOW_MASK | \
STATUS_FRAMERR_MASK ) )
#define BAUDVALUE_LSB ( (uint16_t) (0x00FF) )
#define BAUDVALUE_MSB ( (uint16_t) (0xFF00) )
#define BAUDVALUE_SHIFT ( (uint8_t) (5) )
#define STATUS_ERROR_OFFSET STATUS_PARITYERR_SHIFT
/***************************************************************************//**
* UART_init()
* See "core_uart_apb.h" for details of how to use this function.
*/
void
UART_init
(
UART_instance_t * this_uart,
addr_t base_addr,
uint16_t baud_value,
uint8_t line_config
)
{
uint8_t rx_full;
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( line_config <= MAX_LINE_CONFIG )
HAL_ASSERT( baud_value <= MAX_BAUD_VALUE )
if( ( this_uart != NULL_INSTANCE ) &&
( line_config <= MAX_LINE_CONFIG ) &&
( baud_value <= MAX_BAUD_VALUE ) )
{
/*
* Store lower 8-bits of baud value in CTRL1.
*/
HAL_set_8bit_reg( base_addr, CTRL1, (uint_fast8_t)(baud_value &
BAUDVALUE_LSB ) );
/*
* Extract higher 5-bits of baud value and store in higher 5-bits
* of CTRL2, along with line configuration in lower 3 three bits.
*/
HAL_set_8bit_reg( base_addr, CTRL2, (uint_fast8_t)line_config |
(uint_fast8_t)((baud_value &
BAUDVALUE_MSB) >> BAUDVALUE_SHIFT ) );
this_uart->base_address = base_addr;
#ifndef NDEBUG
{
uint8_t config;
uint8_t temp;
uint16_t baud_val;
baud_val = HAL_get_8bit_reg( this_uart->base_address, CTRL1 );
config = HAL_get_8bit_reg( this_uart->base_address, CTRL2 );
/*
* To resolve operator precedence between & and <<
*/
temp = ( config & (uint8_t)(CTRL2_BAUDVALUE_MASK ) );
baud_val |= (uint16_t)( (uint16_t)(temp) << BAUDVALUE_SHIFT );
config &= (uint8_t)(~CTRL2_BAUDVALUE_MASK);
HAL_ASSERT( baud_val == baud_value );
HAL_ASSERT( config == line_config );
}
#endif
/*
* Flush the receive FIFO of data that may have been received before the
* driver was initialized.
*/
rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
STATUS_RXFULL_MASK;
while ( rx_full )
{
HAL_get_8bit_reg( this_uart->base_address, RXDATA );
rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
STATUS_RXFULL_MASK;
}
/*
* Clear status of the UART instance.
*/
this_uart->status = (uint8_t)0;
}
}
/***************************************************************************//**
* UART_send()
* See "core_uart_apb.h" for details of how to use this function.
*/
void
UART_send
(
UART_instance_t * this_uart,
const uint8_t * tx_buffer,
size_t tx_size
)
{
size_t char_idx;
uint8_t tx_ready;
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( tx_buffer != NULL_BUFFER )
HAL_ASSERT( tx_size > 0 )
if( (this_uart != NULL_INSTANCE) &&
(tx_buffer != NULL_BUFFER) &&
(tx_size > (size_t)0) )
{
for ( char_idx = (size_t)0; char_idx < tx_size; char_idx++ )
{
/* Wait for UART to become ready to transmit. */
do {
tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
STATUS_TXRDY_MASK;
} while ( !tx_ready );
/* Send next character in the buffer. */
HAL_set_8bit_reg( this_uart->base_address, TXDATA,
(uint_fast8_t)tx_buffer[char_idx] );
}
}
}
/***************************************************************************//**
* UART_fill_tx_fifo()
* See "core_uart_apb.h" for details of how to use this function.
*/
size_t
UART_fill_tx_fifo
(
UART_instance_t * this_uart,
const uint8_t * tx_buffer,
size_t tx_size
)
{
uint8_t tx_ready;
size_t size_sent = 0u;
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( tx_buffer != NULL_BUFFER )
HAL_ASSERT( tx_size > 0 )
/* 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_BUFFER) &&
(tx_size > 0u) )
{
tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
STATUS_TXRDY_MASK;
if ( tx_ready )
{
do {
HAL_set_8bit_reg( this_uart->base_address, TXDATA,
(uint_fast8_t)tx_buffer[size_sent] );
size_sent++;
tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
STATUS_TXRDY_MASK;
} while ( (tx_ready) && ( size_sent < tx_size ) );
}
}
return size_sent;
}
/***************************************************************************//**
* UART_get_rx()
* See "core_uart_apb.h" for details of how to use this function.
*/
size_t
UART_get_rx
(
UART_instance_t * this_uart,
uint8_t * rx_buffer,
size_t buff_size
)
{
uint8_t new_status;
uint8_t rx_full;
size_t rx_idx = 0u;
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( rx_buffer != NULL_BUFFER )
HAL_ASSERT( buff_size > 0 )
if( (this_uart != NULL_INSTANCE) &&
(rx_buffer != NULL_BUFFER) &&
(buff_size > 0u) )
{
rx_idx = 0u;
new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );
this_uart->status |= new_status;
rx_full = new_status & STATUS_RXFULL_MASK;
while ( ( rx_full ) && ( rx_idx < buff_size ) )
{
rx_buffer[rx_idx] = HAL_get_8bit_reg( this_uart->base_address,
RXDATA );
rx_idx++;
new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );
this_uart->status |= new_status;
rx_full = new_status & STATUS_RXFULL_MASK;
}
}
return rx_idx;
}
/***************************************************************************//**
* UART_polled_tx_string()
* See "core_uart_apb.h" for details of how to use this function.
*/
void
UART_polled_tx_string
(
UART_instance_t * this_uart,
const uint8_t * p_sz_string
)
{
uint32_t char_idx;
uint8_t tx_ready;
HAL_ASSERT( this_uart != NULL_INSTANCE )
HAL_ASSERT( p_sz_string != NULL_BUFFER )
if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFFER ) )
{
char_idx = 0U;
while( 0U != p_sz_string[char_idx] )
{
/* Wait for UART to become ready to transmit. */
do {
tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
STATUS_TXRDY_MASK;
} while ( !tx_ready );
/* Send next character in the buffer. */
HAL_set_8bit_reg( this_uart->base_address, TXDATA,
(uint_fast8_t)p_sz_string[char_idx] );
char_idx++;
}
}
}
/***************************************************************************//**
* UART_get_rx_status()
* See "core_uart_apb.h" for details of how to use this function.
*/
uint8_t
UART_get_rx_status
(
UART_instance_t * this_uart
)
{
uint8_t status = UART_APB_INVALID_PARAM;
HAL_ASSERT( this_uart != NULL_INSTANCE )
/*
* Extract UART error status and place in lower bits of "status".
* Bit 0 - Parity error status
* Bit 1 - Overflow error status
* Bit 2 - Frame error status
*/
if( this_uart != NULL_INSTANCE )
{
status = ( ( this_uart->status & STATUS_ERROR_MASK ) >>
STATUS_ERROR_OFFSET );
/*
* Clear the sticky status for this instance.
*/
this_uart->status = (uint8_t)0;
}
return status;
}
#ifdef __cplusplus
}
#endif