OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_uart.c] - Diff between revs 48 and 50

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 48 Rev 50
Line 34... Line 34...
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * @file neorv32_uart.c
 * @file neorv32_uart.c
 * @author Stephan Nolting
 * @author Stephan Nolting
 * @brief Universal asynchronous receiver/transmitter (UART) HW driver source file.
 * @brief Universal asynchronous receiver/transmitter (UART0/UART1) HW driver source file.
 *
 *
 * @note These functions should only be used if the UART unit was synthesized (IO_UART_EN = true).
 * @warning UART0 (primary UART) is used as default user console interface for all NEORV32 software framework/library functions.
 
 *
 
 * @note These functions should only be used if the UART0/UART1 unit was synthesized (IO_UART0_EN = true / IO_UART1_EN = true).
 **************************************************************************/
 **************************************************************************/
 
 
#include "neorv32.h"
#include "neorv32.h"
#include "neorv32_uart.h"
#include "neorv32_uart.h"
#include <string.h>
#include <string.h>
Line 50... Line 52...
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
/// \endcond
/// \endcond
 
 
 
 
 
 
 
// #################################################################################################
 
// Compatibility wrappers mapping to UART0 (primary UART)
 
// #################################################################################################
 
 
 
/**********************************************************************//**
 
 * Check if UART0 unit was synthesized.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 *
 
 * @return 0 if UART0 was not synthesized, 1 if UART0 is available.
 
 **************************************************************************/
 
int neorv32_uart_available(void) { return neorv32_uart0_available(); }
 
 
 
 
 
/**********************************************************************//**
 
 * Enable and configure primary UART (UART0).
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 *
 
 * @note The 'UART0_SIM_MODE' compiler flag will configure UART0 for simulation mode: all UART0 TX data will be redirected to simulation output. Use this for simulations only!
 
 * @note To enable simulation mode add <USER_FLAGS+=-DUART0_SIM_MODE> when compiling.
 
 *
 
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
 
 *
 
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
 
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd).
 
 **************************************************************************/
 
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity) { neorv32_uart0_setup(baudrate, parity); }
 
 
 
 
 
/**********************************************************************//**
 
 * Disable UART0.
 
 * @warning This functions maps to UART0 (primary UART).
 
 **************************************************************************/
 
void neorv32_uart_disable(void) { neorv32_uart0_disable(); }
 
 
 
 
 
/**********************************************************************//**
 
 * Send single char via UART0.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is blocking.
 
 *
 
 * @param[in] c Char to be send.
 
 **************************************************************************/
 
void neorv32_uart_putc(char c) { neorv32_uart0_putc(c); }
 
 
 
 
 
/**********************************************************************//**
 
 * Check if UART0 TX is busy.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is blocking.
 
 *
 
 * @return 0 if idle, 1 if busy
 
 **************************************************************************/
 
int neorv32_uart_tx_busy(void) { return neorv32_uart0_tx_busy(); }
 
 
 
 
 
/**********************************************************************//**
 
 * Get char from UART0.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is blocking and does not check for UART frame/parity errors.
 
 *
 
 * @return Received char.
 
 **************************************************************************/
 
char neorv32_uart_getc(void) { return neorv32_uart0_getc(); }
 
 
 
 
 
/**********************************************************************//**
 
 * Check if UART0 has received a char.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is non-blocking.
 
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
 
 *
 
 * @return =!0 when a char has been received.
 
 **************************************************************************/
 
int neorv32_uart_char_received(void) { return neorv32_uart0_char_received(); }
 
 
 
 
 
/**********************************************************************//**
 
 * Get char from UART0 (and check errors).
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is non-blocking and checks for frame and parity errors.
 
 *
 
 * @param[in,out] data Received char.
 
 * @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
 
 **************************************************************************/
 
int neorv32_uart_getc_secure(char *data) { return neorv32_uart0_getc_secure(data); }
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Check if UART unit was synthesized.
 * Get a received char from UART0.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is non-blocking.
 
 * @note Should only be used in combination with neorv32_uart_char_received(void).
 
 *
 
 * @return Received char.
 
 **************************************************************************/
 
char neorv32_uart_char_received_get(void) { return neorv32_uart0_char_received_get(); }
 
 
 
 
 
/**********************************************************************//**
 
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is blocking.
 *
 *
 * @return 0 if UART was not synthesized, 1 if UART is available.
 * @param[in] s Pointer to string.
 **************************************************************************/
 **************************************************************************/
int neorv32_uart_available(void) {
void neorv32_uart_print(const char *s) { neorv32_uart0_print(s); }
 
 
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_UART)) {
 
 
/**********************************************************************//**
 
 * Custom version of 'printf' function using UART0.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is blocking.
 
 *
 
 * @param[in] format Pointer to format string.
 
 *
 
 * <TABLE>
 
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
 
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
 
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
 
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
 
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
 
 * </TABLE>
 
 **************************************************************************/
 
void neorv32_uart_printf(const char *format, ...) { neorv32_uart0_printf(format); }
 
 
 
 
 
/**********************************************************************//**
 
 * Simplified custom version of 'scanf' function for UART0.
 
 *
 
 * @warning This functions maps to UART0 (primary UART).
 
 * @note This function is blocking.
 
 *
 
 * @param[in,out] buffer Pointer to array of chars to store string.
 
 * @param[in] max_size Maximum number of chars to sample.
 
 * @param[in] echo Echo UART input when 1.
 
 * @return Number of chars read.
 
 **************************************************************************/
 
int neorv32_uart_scan(char *buffer, int max_size, int echo) { return neorv32_uart0_scan(buffer, max_size, echo); }
 
 
 
 
 
 
 
// #################################################################################################
 
// Primary UART (UART0)
 
// #################################################################################################
 
 
 
/**********************************************************************//**
 
 * Check if UART0 unit was synthesized.
 
 *
 
 * @return 0 if UART0 was not synthesized, 1 if UART0 is available.
 
 **************************************************************************/
 
int neorv32_uart0_available(void) {
 
 
 
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_UART0)) {
    return 1;
    return 1;
  }
  }
  else {
  else {
    return 0;
    return 0;
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Enable and configure UART.
 * Enable and configure primary UART (UART0).
 *
 *
 * @note The 'UART_SIM_MODE' compiler flag will configure UART for simulation mode: all UART TX data will be redirected to simulation output. Use this for simulations only!
 * @note The 'UART0_SIM_MODE' compiler flag will configure UART0 for simulation mode: all UART0 TX data will be redirected to simulation output. Use this for simulations only!
 * @note To enable simulation mode add <USER_FLAGS+=-DUART_SIM_MODE> when compiling.
 * @note To enable simulation mode add <USER_FLAGS+=-DUART0_SIM_MODE> when compiling.
 *
 *
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
 *
 *
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
 * @param[in] parity PArity configuration (00=off, 10=even, 11=odd).
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd).
 **************************************************************************/
 **************************************************************************/
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity) {
void neorv32_uart0_setup(uint32_t baudrate, uint8_t parity) {
 
 
  UART_CT = 0; // reset
  UART0_CT = 0; // reset
 
 
  uint32_t clock = SYSINFO_CLK;
  uint32_t clock = SYSINFO_CLK;
  uint16_t i = 0; // BAUD rate divisor
  uint16_t i = 0; // BAUD rate divisor
  uint8_t p = 0; // initial prsc = CLK/2
  uint8_t p = 0; // initial prsc = CLK/2
 
 
Line 119... Line 277...
  uart_en = uart_en << UART_CT_EN;
  uart_en = uart_en << UART_CT_EN;
 
 
  uint32_t parity_config = (uint32_t)(parity & 3);
  uint32_t parity_config = (uint32_t)(parity & 3);
  parity_config = parity_config << UART_CT_PMODE0;
  parity_config = parity_config << UART_CT_PMODE0;
 
 
  /* Enable the UART for SIM mode. */
  /* Enable UART0 for SIM mode. */
  /* USE THIS ONLY FOR SIMULATION! */
  /* USE THIS ONLY FOR SIMULATION! */
#ifdef UART_SIM_MODE
#ifdef UART_SIM_MODE
  #warning UART_SIM_MODE enabled! Sending all UART.TX data to text.io simulation output instead of real UART transmitter. Use this for simulations only!
  #warning <UART_SIM_MODE> is obsolete (but still supported for compatibility). Please consider using the new flag <UART0_SIM_MODE>.
 
#endif
 
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
 
  #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only!
  uint32_t sim_mode = 1 << UART_CT_SIM_MODE;
  uint32_t sim_mode = 1 << UART_CT_SIM_MODE;
#else
#else
  uint32_t sim_mode = 0;
  uint32_t sim_mode = 0;
#endif
#endif
 
 
  UART_CT = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode;
  UART0_CT = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Disable UART.
 * Disable UART0.
 **************************************************************************/
 **************************************************************************/
void neorv32_uart_disable(void) {
void neorv32_uart0_disable(void) {
 
 
  UART_CT &= ~((uint32_t)(1 << UART_CT_EN));
  UART0_CT &= ~((uint32_t)(1 << UART_CT_EN));
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Send single char via UART.
 * Send single char via UART0.
 *
 *
 * @note This function is blocking.
 * @note This function is blocking.
 *
 *
 * @param[in] c Char to be send.
 * @param[in] c Char to be send.
 **************************************************************************/
 **************************************************************************/
void neorv32_uart_putc(char c) {
void neorv32_uart0_putc(char c) {
 
 
#ifdef UART_SIM_MODE
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
  UART_DATA = ((uint32_t)c) << UART_DATA_LSB;
  UART0_DATA = ((uint32_t)c) << UART_DATA_LSB;
#else
#else
  // wait for previous transfer to finish
  // wait for previous transfer to finish
  while ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0);
  while ((UART0_CT & (1<<UART_CT_TX_BUSY)) != 0);
  UART_DATA = ((uint32_t)c) << UART_DATA_LSB;
  UART0_DATA = ((uint32_t)c) << UART_DATA_LSB;
#endif
#endif
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Check if UART TX is busy.
 * Check if UART0 TX is busy.
 *
 *
 * @note This function is blocking.
 * @note This function is blocking.
 *
 *
 * @return 0 if idle, 1 if busy
 * @return 0 if idle, 1 if busy
 **************************************************************************/
 **************************************************************************/
int neorv32_uart_tx_busy(void) {
int neorv32_uart0_tx_busy(void) {
 
 
  if ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0) {
  if ((UART0_CT & (1<<UART_CT_TX_BUSY)) != 0) {
    return 1;
    return 1;
  }
  }
  return 0;
  return 0;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Get char from UART.
 * Get char from UART0.
 *
 *
 * @note This function is blocking and does not check for UART frame/parity errors.
 * @note This function is blocking and does not check for UART frame/parity errors.
 *
 *
 * @return Received char.
 * @return Received char.
 **************************************************************************/
 **************************************************************************/
char neorv32_uart_getc(void) {
char neorv32_uart0_getc(void) {
 
 
  uint32_t d = 0;
  uint32_t d = 0;
  while (1) {
  while (1) {
    d = UART_DATA;
    d = UART0_DATA;
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
      return (char)d;
      return (char)d;
    }
    }
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Get char from UART (and check errors).
 * Get char from UART0 (and check errors).
 *
 *
 * @note This function is non-blocking and checks for frame and parity errors.
 * @note This function is non-blocking and checks for frame and parity errors.
 *
 *
 * @param[in,out] data Received char.
 * @param[in,out] data Received char.
 * @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
 * @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
 **************************************************************************/
 **************************************************************************/
int neorv32_uart_getc_secure(char *data) {
int neorv32_uart0_getc_secure(char *data) {
 
 
  uint32_t uart_rx = UART_DATA;
  uint32_t uart_rx = UART0_DATA;
  if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
  if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
 
 
    int status = 0;
    int status = 0;
 
 
    // check for frame error
    // check for frame error
Line 236... Line 397...
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Check if UART has received a char.
 * Check if UART0 has received a char.
 *
 *
 * @note This function is non-blocking.
 * @note This function is non-blocking.
 * @note Use neorv32_uart_char_received_get(void) to get the char.
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
 *
 *
 * @return =!0 when a char has been received.
 * @return =!0 when a char has been received.
 **************************************************************************/
 **************************************************************************/
int neorv32_uart_char_received(void) {
int neorv32_uart0_char_received(void) {
 
 
  if ((UART_DATA & (1<<UART_DATA_AVAIL)) != 0) {
  if ((UART0_DATA & (1<<UART_DATA_AVAIL)) != 0) {
    return 1;
    return 1;
  }
  }
  else {
  else {
    return 0;
    return 0;
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Get a received char.
 * Get a received char from UART0.
 *
 *
 * @note This function is non-blocking.
 * @note This function is non-blocking.
 * @note Should only be used in combination with neorv32_uart_char_received(void).
 * @note Should only be used in combination with neorv32_uart_char_received(void).
 *
 *
 * @return Received char.
 * @return Received char.
 **************************************************************************/
 **************************************************************************/
char neorv32_uart_char_received_get(void) {
char neorv32_uart0_char_received_get(void) {
 
 
  return (char)UART_DATA;
  return (char)UART0_DATA;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Print string (zero-terminated) via UART. Print full line break "\r\n" for every '\n'.
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
 *
 *
 * @note This function is blocking.
 * @note This function is blocking.
 *
 *
 * @param[in] s Pointer to string.
 * @param[in] s Pointer to string.
 **************************************************************************/
 **************************************************************************/
void neorv32_uart_print(const char *s) {
void neorv32_uart0_print(const char *s) {
 
 
  char c = 0;
  char c = 0;
  while ((c = *s++)) {
  while ((c = *s++)) {
    if (c == '\n') {
    if (c == '\n') {
      neorv32_uart_putc('\r');
      neorv32_uart0_putc('\r');
    }
    }
    neorv32_uart_putc(c);
    neorv32_uart0_putc(c);
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Private function for 'neorv32_printf' to convert into decimal.
 * Custom version of 'printf' function using UART0.
 *
 *
 * @param[in] x Unsigned input number.
 * @note This function is blocking.
 * @param[in,out] res Pointer for storing the reuslting number string (11 chars).
 *
 
 * @param[in] format Pointer to format string.
 
 *
 
 * <TABLE>
 
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
 
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
 
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
 
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
 
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
 
 * </TABLE>
 **************************************************************************/
 **************************************************************************/
static void __neorv32_uart_itoa(uint32_t x, char *res) {
void neorv32_uart0_printf(const char *format, ...) {
 
 
  static const char numbers[] = "0123456789";
  char c, string_buf[11];
  char buffer1[11];
  int32_t n;
  uint16_t i, j;
 
 
 
  buffer1[10] = '\0';
  va_list a;
  res[10] = '\0';
  va_start(a, format);
 
 
  // convert
  while ((c = *format++)) {
  for (i=0; i<10; i++) {
    if (c == '%') {
    buffer1[i] = numbers[x%10];
      c = *format++;
    x /= 10;
      switch (c) {
 
        case 's': // string
 
          neorv32_uart0_print(va_arg(a, char*));
 
          break;
 
        case 'c': // char
 
          neorv32_uart0_putc((char)va_arg(a, int));
 
          break;
 
        case 'i': // 32-bit signed
 
          n = (int32_t)va_arg(a, int32_t);
 
          if (n < 0) {
 
            n = -n;
 
            neorv32_uart0_putc('-');
 
          }
 
          __neorv32_uart_itoa((uint32_t)n, string_buf);
 
          neorv32_uart0_print(string_buf);
 
          break;
 
        case 'u': // 32-bit unsigned
 
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
 
          neorv32_uart0_print(string_buf);
 
          break;
 
        case 'x': // 32-bit hexadecimal
 
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
 
          neorv32_uart0_print(string_buf);
 
          break;
 
        default:
 
          return;
 
      }
 
    }
 
    else {
 
      if (c == '\n') {
 
        neorv32_uart0_putc('\r');
 
      }
 
      neorv32_uart0_putc(c);
 
    }
 
  }
 
  va_end(a);
  }
  }
 
 
  // delete 'leading' zeros
 
  for (i=9; i!=0; i--) {
/**********************************************************************//**
    if (buffer1[i] == '0')
 * Simplified custom version of 'scanf' function for UART0.
      buffer1[i] = '\0';
 *
    else
 * @note This function is blocking.
 
 *
 
 * @param[in,out] buffer Pointer to array of chars to store string.
 
 * @param[in] max_size Maximum number of chars to sample.
 
 * @param[in] echo Echo UART input when 1.
 
 * @return Number of chars read.
 
 **************************************************************************/
 
int neorv32_uart0_scan(char *buffer, int max_size, int echo) {
 
 
 
  char c = 0;
 
  int length = 0;
 
 
 
  while (1) {
 
    c = neorv32_uart0_getc();
 
    if (c == '\b') { // BACKSPACE
 
      if (length != 0) {
 
        if (echo) {
 
          neorv32_uart0_print("\b \b"); // delete last char in console
 
        }
 
        buffer--;
 
        length--;
 
      }
 
    }
 
    else if (c == '\r') // carriage return
      break;
      break;
 
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
 
      if (echo) {
 
        neorv32_uart0_putc(c); // echo
  }
  }
 
      *buffer++ = c;
 
      length++;
 
    }
 
  }
 
  *buffer = '\0'; // terminate string
 
 
  // reverse
  return length;
  j = 0;
}
  do {
 
    if (buffer1[i] != '\0')
 
      res[j++] = buffer1[i];
 
  } while (i--);
 
 
 
  res[j] = '\0'; // terminate result string
 
 
 
 
// #################################################################################################
 
// Secondary UART (UART1)
 
// #################################################################################################
 
 
 
/**********************************************************************//**
 
 * Check if UART1 unit was synthesized.
 
 *
 
 * @return 0 if UART1 was not synthesized, 1 if UART1 is available.
 
 **************************************************************************/
 
int neorv32_uart1_available(void) {
 
 
 
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_UART1)) {
 
    return 1;
 
  }
 
  else {
 
    return 0;
 
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Private function for 'neorv32_printf' to convert into hexadecimal.
 * Enable and configure secondary UART (UART1).
 *
 *
 * @param[in] x Unsigned input number.
 * @note The 'UART1_SIM_MODE' compiler flag will configure UART1 for simulation mode: all UART1 TX data will be redirected to simulation output. Use this for simulations only!
 * @param[in,out] res Pointer for storing the reuslting number string (9 chars).
 * @note To enable simulation mode add <USER_FLAGS+=-DUART1_SIM_MODE> when compiling.
 
 *
 
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
 
 *
 
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
 
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd).
 **************************************************************************/
 **************************************************************************/
static void __neorv32_uart_tohex(uint32_t x, char *res) {
void neorv32_uart1_setup(uint32_t baudrate, uint8_t parity) {
 
 
  static const char symbols[] = "0123456789abcdef";
  UART1_CT = 0; // reset
 
 
  int i;
  uint32_t clock = SYSINFO_CLK;
  for (i=0; i<8; i++) { // nibble by bibble
  uint16_t i = 0; // BAUD rate divisor
    uint32_t num_tmp = x >> (4*i);
  uint8_t p = 0; // initial prsc = CLK/2
    res[7-i] = (char)symbols[num_tmp & 0x0f];
 
 
  // raw clock prescaler
 
#ifdef __riscv_div
 
  // use div instructions
 
  i = (uint16_t)(clock / (2*baudrate));
 
#else
 
  // division via repeated subtraction
 
  while (clock >= 2*baudrate) {
 
    clock -= 2*baudrate;
 
    i++;
  }
  }
 
#endif
 
 
  res[8] = '\0'; // terminate result string
  // find baud prescaler (12-bit wide))
 
  while (i >= 0x0fff) {
 
    if ((p == 2) || (p == 4))
 
      i >>= 3;
 
    else
 
      i >>= 1;
 
    p++;
 
  }
 
 
 
  uint32_t clk_prsc = (uint32_t)p;
 
  clk_prsc = clk_prsc << UART_CT_PRSC0;
 
 
 
  uint32_t baud_prsc = (uint32_t)i;
 
  baud_prsc = baud_prsc - 1;
 
  baud_prsc = baud_prsc << UART_CT_BAUD00;
 
 
 
  uint32_t uart_en = 1;
 
  uart_en = uart_en << UART_CT_EN;
 
 
 
  uint32_t parity_config = (uint32_t)(parity & 3);
 
  parity_config = parity_config << UART_CT_PMODE0;
 
 
 
  /* Enable UART1 for SIM mode. */
 
  /* USE THIS ONLY FOR SIMULATION! */
 
#ifdef UART1_SIM_MODE
 
  #warning UART1_SIM_MODE (secondary UART) enabled! Sending all UART1.TX data to text.io simulation output instead of real UART1 transmitter. Use this for simulations only!
 
  uint32_t sim_mode = 1 << UART_CT_SIM_MODE;
 
#else
 
  uint32_t sim_mode = 0;
 
#endif
 
 
 
  UART1_CT = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode;
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Disable UART1.
 
 **************************************************************************/
 
void neorv32_uart1_disable(void) {
 
 
 
  UART1_CT &= ~((uint32_t)(1 << UART_CT_EN));
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Send single char via UART1.
 
 *
 
 * @note This function is blocking.
 
 *
 
 * @param[in] c Char to be send.
 
 **************************************************************************/
 
void neorv32_uart1_putc(char c) {
 
 
 
#ifdef UART1_SIM_MODE
 
  UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
 
#else
 
  // wait for previous transfer to finish
 
  while ((UART1_CT & (1<<UART_CT_TX_BUSY)) != 0);
 
  UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
 
#endif
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Custom version of 'printf' function.
 * Check if UART1 TX is busy.
 
 *
 
 * @note This function is blocking.
 
 *
 
 * @return 0 if idle, 1 if busy
 
 **************************************************************************/
 
int neorv32_uart1_tx_busy(void) {
 
 
 
  if ((UART1_CT & (1<<UART_CT_TX_BUSY)) != 0) {
 
    return 1;
 
  }
 
  return 0;
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Get char from UART1.
 
 *
 
 * @note This function is blocking and does not check for UART frame/parity errors.
 
 *
 
 * @return Received char.
 
 **************************************************************************/
 
char neorv32_uart1_getc(void) {
 
 
 
  uint32_t d = 0;
 
  while (1) {
 
    d = UART1_DATA;
 
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
 
      return (char)d;
 
    }
 
  }
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Get char from UART1 (and check errors).
 
 *
 
 * @note This function is non-blocking and checks for frame and parity errors.
 
 *
 
 * @param[in,out] data Received char.
 
 * @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
 
 **************************************************************************/
 
int neorv32_uart1_getc_secure(char *data) {
 
 
 
  uint32_t uart_rx = UART1_DATA;
 
  if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
 
 
 
    int status = 0;
 
 
 
    // check for frame error
 
    if (uart_rx & (1<<UART_DATA_FERR)) {
 
      status -= 1;
 
    }
 
 
 
    // check for parity error
 
    if (uart_rx & (1<<UART_DATA_PERR)) {
 
      status -= 2;
 
    }
 
 
 
    if (status == 0) {
 
      status = 1;
 
    }
 
 
 
    // get received byte
 
    *data =  (char)uart_rx;
 
 
 
    return status;
 
  }
 
  else {
 
    return 0;
 
  }
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Check if UART1 has received a char.
 
 *
 
 * @note This function is non-blocking.
 
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
 
 *
 
 * @return =!0 when a char has been received.
 
 **************************************************************************/
 
int neorv32_uart1_char_received(void) {
 
 
 
  if ((UART1_DATA & (1<<UART_DATA_AVAIL)) != 0) {
 
    return 1;
 
  }
 
  else {
 
    return 0;
 
  }
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Get a received char from UART1.
 
 *
 
 * @note This function is non-blocking.
 
 * @note Should only be used in combination with neorv32_uart_char_received(void).
 
 *
 
 * @return Received char.
 
 **************************************************************************/
 
char neorv32_uart1_char_received_get(void) {
 
 
 
  return (char)UART1_DATA;
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Print string (zero-terminated) via UART1. Print full line break "\r\n" for every '\n'.
 
 *
 
 * @note This function is blocking.
 
 *
 
 * @param[in] s Pointer to string.
 
 **************************************************************************/
 
void neorv32_uart1_print(const char *s) {
 
 
 
  char c = 0;
 
  while ((c = *s++)) {
 
    if (c == '\n') {
 
      neorv32_uart1_putc('\r');
 
    }
 
    neorv32_uart1_putc(c);
 
  }
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Custom version of 'printf' function using UART1.
 *
 *
 * @note This function is blocking.
 * @note This function is blocking.
 *
 *
 * @param[in] format Pointer to format string.
 * @param[in] format Pointer to format string.
 *
 *
Line 362... Line 812...
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
 * </TABLE>
 * </TABLE>
 **************************************************************************/
 **************************************************************************/
void neorv32_uart_printf(const char *format, ...) {
void neorv32_uart1_printf(const char *format, ...) {
 
 
  char c, string_buf[11];
  char c, string_buf[11];
  int32_t n;
  int32_t n;
 
 
  va_list a;
  va_list a;
Line 375... Line 825...
  while ((c = *format++)) {
  while ((c = *format++)) {
    if (c == '%') {
    if (c == '%') {
      c = *format++;
      c = *format++;
      switch (c) {
      switch (c) {
        case 's': // string
        case 's': // string
          neorv32_uart_print(va_arg(a, char*));
          neorv32_uart1_print(va_arg(a, char*));
          break;
          break;
        case 'c': // char
        case 'c': // char
          neorv32_uart_putc((char)va_arg(a, int));
          neorv32_uart1_putc((char)va_arg(a, int));
          break;
          break;
        case 'i': // 32-bit signed
        case 'i': // 32-bit signed
          n = (int32_t)va_arg(a, int32_t);
          n = (int32_t)va_arg(a, int32_t);
          if (n < 0) {
          if (n < 0) {
            n = -n;
            n = -n;
            neorv32_uart_putc('-');
            neorv32_uart1_putc('-');
          }
          }
          __neorv32_uart_itoa((uint32_t)n, string_buf);
          __neorv32_uart_itoa((uint32_t)n, string_buf);
          neorv32_uart_print(string_buf);
          neorv32_uart1_print(string_buf);
          break;
          break;
        case 'u': // 32-bit unsigned
        case 'u': // 32-bit unsigned
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
          neorv32_uart_print(string_buf);
          neorv32_uart1_print(string_buf);
          break;
          break;
        case 'x': // 32-bit hexadecimal
        case 'x': // 32-bit hexadecimal
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
          neorv32_uart_print(string_buf);
          neorv32_uart1_print(string_buf);
          break;
          break;
        default:
        default:
          return;
          return;
      }
      }
    }
    }
    else {
    else {
      if (c == '\n') {
      if (c == '\n') {
        neorv32_uart_putc('\r');
        neorv32_uart1_putc('\r');
      }
      }
      neorv32_uart_putc(c);
      neorv32_uart1_putc(c);
    }
    }
  }
  }
  va_end(a);
  va_end(a);
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Simplified custom version of 'scanf' function.
 * Simplified custom version of 'scanf' function for UART1.
 *
 *
 * @note This function is blocking.
 * @note This function is blocking.
 *
 *
 * @param[in,out] buffer Pointer to array of chars to store string.
 * @param[in,out] buffer Pointer to array of chars to store string.
 * @param[in] max_size Maximum number of chars to sample.
 * @param[in] max_size Maximum number of chars to sample.
 * @param[in] echo Echo UART input when 1.
 * @param[in] echo Echo UART input when 1.
 * @return Number of chars read.
 * @return Number of chars read.
 **************************************************************************/
 **************************************************************************/
int neorv32_uart_scan(char *buffer, int max_size, int echo) {
int neorv32_uart1_scan(char *buffer, int max_size, int echo) {
 
 
  char c = 0;
  char c = 0;
  int length = 0;
  int length = 0;
 
 
  while (1) {
  while (1) {
    c = neorv32_uart_getc();
    c = neorv32_uart1_getc();
    if (c == '\b') { // BACKSPACE
    if (c == '\b') { // BACKSPACE
      if (length != 0) {
      if (length != 0) {
        if (echo) {
        if (echo) {
          neorv32_uart_print("\b \b"); // delete last char in console
          neorv32_uart1_print("\b \b"); // delete last char in console
        }
        }
        buffer--;
        buffer--;
        length--;
        length--;
      }
      }
    }
    }
    else if (c == '\r') // carriage return
    else if (c == '\r') // carriage return
      break;
      break;
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
      if (echo) {
      if (echo) {
        neorv32_uart_putc(c); // echo
        neorv32_uart1_putc(c); // echo
      }
      }
      *buffer++ = c;
      *buffer++ = c;
      length++;
      length++;
    }
    }
  }
  }
Line 454... Line 904...
 
 
  return length;
  return length;
}
}
 
 
 
 
 No newline at end of file
 No newline at end of file
 
 
 
// #################################################################################################
 
// Shared functions
 
// #################################################################################################
 
 
 
/**********************************************************************//**
 
 * Private function for 'neorv32_printf' to convert into decimal.
 
 *
 
 * @param[in] x Unsigned input number.
 
 * @param[in,out] res Pointer for storing the reuslting number string (11 chars).
 
 **************************************************************************/
 
static void __neorv32_uart_itoa(uint32_t x, char *res) {
 
 
 
  static const char numbers[] = "0123456789";
 
  char buffer1[11];
 
  uint16_t i, j;
 
 
 
  buffer1[10] = '\0';
 
  res[10] = '\0';
 
 
 
  // convert
 
  for (i=0; i<10; i++) {
 
    buffer1[i] = numbers[x%10];
 
    x /= 10;
 
  }
 
 
 
  // delete 'leading' zeros
 
  for (i=9; i!=0; i--) {
 
    if (buffer1[i] == '0')
 
      buffer1[i] = '\0';
 
    else
 
      break;
 
  }
 
 
 
  // reverse
 
  j = 0;
 
  do {
 
    if (buffer1[i] != '\0')
 
      res[j++] = buffer1[i];
 
  } while (i--);
 
 
 
  res[j] = '\0'; // terminate result string
 
}
 
 
 
 
 
/**********************************************************************//**
 
 * Private function for 'neorv32_printf' to convert into hexadecimal.
 
 *
 
 * @param[in] x Unsigned input number.
 
 * @param[in,out] res Pointer for storing the reuslting number string (9 chars).
 
 **************************************************************************/
 
static void __neorv32_uart_tohex(uint32_t x, char *res) {
 
 
 
  static const char symbols[] = "0123456789abcdef";
 
 
 
  int i;
 
  for (i=0; i<8; i++) { // nibble by bibble
 
    uint32_t num_tmp = x >> (4*i);
 
    res[7-i] = (char)symbols[num_tmp & 0x0f];
 
  }
 
 
 
  res[8] = '\0'; // terminate result string
 
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.