/* uart.c. UART support functions
|
/* uart.c. UART support functions
|
|
|
Copyright (C) 2004, Jacob Bower
|
Copyright (C) 2004, Jacob Bower
|
Copyright (C) 2010, Embecosm Limited <info@embecosm.com>
|
Copyright (C) 2010, Embecosm Limited <info@embecosm.com>
|
|
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
|
|
This file is part of Newlib.
|
This file is part of Newlib.
|
|
|
The original work by Jacob Bower is provided as-is without any kind of
|
The original work by Jacob Bower is provided as-is without any kind of
|
warranty. Use it at your own risk!
|
warranty. Use it at your own risk!
|
|
|
All subsequent work is bound by version 3 of the GPL as follows.
|
All subsequent work is bound by version 3 of the GPL as follows.
|
|
|
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
under the terms of the GNU General Public License as published by the Free
|
under the terms of the GNU General Public License as published by the Free
|
Software Foundation; either version 3 of the License, or (at your option)
|
Software Foundation; either version 3 of the License, or (at your option)
|
any later version.
|
any later version.
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
more details.
|
more details.
|
|
|
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
with this program. If not, see <http:#www.gnu.org/licenses/>. */
|
with this program. If not, see <http:#www.gnu.org/licenses/>. */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/* This program is commented throughout in a fashion suitable for processing
|
/* This program is commented throughout in a fashion suitable for processing
|
with Doxygen. */
|
with Doxygen. */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
|
|
#include "or1ksim-board.h"
|
#include "or1ksim-board.h"
|
#include "uart.h"
|
#include "uart.h"
|
|
|
|
|
/*! Macro to access a UART register */
|
/*! Macro to access a UART register */
|
#define UREG8(reg) REG8 (UART_BASE + reg)
|
#define UREG8(reg) REG8 (UART_BASE + reg)
|
|
|
/*! Macro to check if transmit and transmit holding registers are both empty. */
|
/*! Macro to check if transmit and transmit holding registers are both empty. */
|
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
|
|
/*! Macro to wait until a char has been transmitted */
|
/*! Macro to wait until a char has been transmitted */
|
#define WAIT_FOR_XMITR \
|
#define WAIT_FOR_XMITR \
|
do \
|
do \
|
{ \
|
{ \
|
lsr = UREG8 (UART_LSR); \
|
lsr = UREG8 (UART_LSR); \
|
} \
|
} \
|
while ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
|
while ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
|
|
|
/*! Macro to wait until a char can be transmitted */
|
/*! Macro to wait until a char can be transmitted */
|
#define WAIT_FOR_THRE \
|
#define WAIT_FOR_THRE \
|
do \
|
do \
|
{ \
|
{ \
|
lsr = UREG8 (UART_LSR); \
|
lsr = UREG8 (UART_LSR); \
|
} \
|
} \
|
while ((lsr & UART_LSR_THRE) != UART_LSR_THRE)
|
while ((lsr & UART_LSR_THRE) != UART_LSR_THRE)
|
|
|
/* Macro to see if a character has been received */
|
/* Macro to see if a character has been received */
|
#define CHECK_FOR_CHAR (UREG8 (UART_LSR) & UART_LSR_DR)
|
#define CHECK_FOR_CHAR (UREG8 (UART_LSR) & UART_LSR_DR)
|
|
|
/* Macro to wait until a character is received */
|
/* Macro to wait until a character is received */
|
#define WAIT_FOR_CHAR \
|
#define WAIT_FOR_CHAR \
|
do { \
|
do { \
|
lsr = UREG8 (UART_LSR); \
|
lsr = UREG8 (UART_LSR); \
|
} while ((lsr & UART_LSR_DR) != UART_LSR_DR)
|
} while ((lsr & UART_LSR_DR) != UART_LSR_DR)
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/*!Initialize the UART */
|
/*!Initialize the UART */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
void
|
void
|
_uart_init ()
|
_uart_init ()
|
{
|
{
|
int divisor;
|
int divisor;
|
|
|
/* Reset receiver and transmiter */
|
/* Reset receiver and transmiter */
|
UREG8 (UART_FCR) = UART_FCR_ENABLE_FIFO |
|
UREG8 (UART_FCR) = UART_FCR_ENABLE_FIFO |
|
UART_FCR_CLEAR_RCVR |
|
UART_FCR_CLEAR_RCVR |
|
UART_FCR_CLEAR_XMIT |
|
UART_FCR_CLEAR_XMIT |
|
UART_FCR_TRIGGER_14;
|
UART_FCR_TRIGGER_14;
|
|
|
/* Disable all interrupts */
|
/* Disable all interrupts */
|
UREG8 (UART_IER) = 0x00;
|
UREG8 (UART_IER) = 0x00;
|
|
|
/* Set 8 bit char, 1 stop bit, no parity */
|
/* Set 8 bit char, 1 stop bit, no parity */
|
UREG8 (UART_LCR) = UART_LCR_WLEN8 & ~(UART_LCR_STOP | UART_LCR_PARITY);
|
UREG8 (UART_LCR) = UART_LCR_WLEN8 & ~(UART_LCR_STOP | UART_LCR_PARITY);
|
|
|
/* Set baud rate */
|
/* Set baud rate */
|
divisor = IN_CLK / (16 * UART_BAUD_RATE);
|
divisor = IN_CLK / (16 * UART_BAUD_RATE);
|
|
|
UREG8 (UART_LCR) |= UART_LCR_DLAB;
|
UREG8 (UART_LCR) |= UART_LCR_DLAB;
|
UREG8 (UART_DLL) = divisor & 0x000000ff;
|
UREG8 (UART_DLL) = divisor & 0x000000ff;
|
UREG8 (UART_DLM) = (divisor >> 8) & 0x000000ff;
|
UREG8 (UART_DLM) = (divisor >> 8) & 0x000000ff;
|
UREG8 (UART_LCR) &= ~(UART_LCR_DLAB);
|
UREG8 (UART_LCR) &= ~(UART_LCR_DLAB);
|
|
|
} /* _uart_init () */
|
} /* _uart_init () */
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/*!Put a character out on the UART
|
/*!Put a character out on the UART
|
|
|
@param[in] c The character to output */
|
@param[in] c The character to output */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
void _uart_putc (char c)
|
void _uart_putc (char c)
|
{
|
{
|
unsigned char lsr;
|
unsigned char lsr;
|
|
|
/* Wait until we are free to transmit */
|
/* Wait until we are free to transmit */
|
WAIT_FOR_THRE;
|
WAIT_FOR_THRE;
|
|
|
/* Put the character to be trasmitted. If it is newline (line feed) add a
|
/* Put the character to be transmitted and wait until it has gone. */
|
carriage return, and wait until it has gone. */
|
|
UREG8 (UART_TX) = c;
|
UREG8 (UART_TX) = c;
|
|
|
if ('\n' == c)
|
|
{
|
|
WAIT_FOR_THRE;
|
|
UREG8 (UART_TX) = '\r';
|
|
}
|
|
|
|
WAIT_FOR_XMITR;
|
WAIT_FOR_XMITR;
|
|
|
} /* _uart_putc () */
|
} /* _uart_putc () */
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/*!Get a character from the UART
|
/*!Get a character from the UART
|
|
|
@reurn The character read. */
|
@reurn The character read. */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
char
|
char
|
_uart_getc ()
|
_uart_getc ()
|
{
|
{
|
unsigned char lsr;
|
unsigned char lsr;
|
char c;
|
char c;
|
|
|
/* Wait until a char is available, then get it. */
|
/* Wait until a char is available, then get it. */
|
WAIT_FOR_CHAR;
|
WAIT_FOR_CHAR;
|
|
|
return UREG8 (UART_RX);
|
return UREG8 (UART_RX);
|
|
|
} /* _uart_getc () */
|
} /* _uart_getc () */
|
|
|