Line 1... |
Line 1... |
// #################################################################################################
|
// #################################################################################################
|
// # << NEORV32: neorv32_uart.c - Universal Asynchronous Receiver/Transmitter (UART) HW Driver >> #
|
// # << NEORV32: neorv32_uart.c - Universal Asynchronous Receiver/Transmitter (UART) HW Driver >> #
|
// # ********************************************************************************************* #
|
// # ********************************************************************************************* #
|
// # BSD 3-Clause License #
|
// # BSD 3-Clause License #
|
// # #
|
// # #
|
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
|
// # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
|
// # #
|
// # #
|
// # Redistribution and use in source and binary forms, with or without modification, are #
|
// # Redistribution and use in source and binary forms, with or without modification, are #
|
// # permitted provided that the following conditions are met: #
|
// # permitted provided that the following conditions are met: #
|
// # #
|
// # #
|
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
Line 50... |
Line 50... |
|
|
/// \cond
|
/// \cond
|
// Private functions
|
// Private functions
|
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
|
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
|
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
|
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
|
|
static void __neorv32_uart_touppercase(uint32_t len, char *ptr) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
|
/// \endcond
|
/// \endcond
|
|
|
|
|
// #################################################################################################
|
// #################################################################################################
|
// Primary UART (UART0)
|
// Primary UART (UART0)
|
Line 95... |
Line 96... |
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
|
|
|
// raw clock prescaler
|
// raw clock prescaler
|
#ifndef make_bootloader
|
#ifndef make_bootloader
|
|
// use div instructions
|
i = (uint16_t)(clock / (2*baudrate));
|
i = (uint16_t)(clock / (2*baudrate));
|
#else
|
#else
|
// division via repeated subtraction (minimal size, only for bootloader)
|
// division via repeated subtraction (minimal size, only for bootloader)
|
while (clock >= 2*baudrate) {
|
while (clock >= 2*baudrate) {
|
clock -= 2*baudrate;
|
clock -= 2*baudrate;
|
Line 322... |
Line 324... |
* @param[in] format Pointer to format string.
|
* @param[in] format Pointer to format string.
|
*
|
*
|
* <TABLE>
|
* <TABLE>
|
* <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
|
* <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
|
* <TR><TD>%c</TD><TD>Single char</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>%d/%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 - lower-case</TD></TR>
|
|
* <TR><TD>%X</TD><TD>32-bit number, printed as 8-char hexadecimal - upper-case</TD></TR>
|
|
* <TR><TD>%p</TD><TD>32-bit pointer, printed as 8-char hexadecimal - lower-case</TD></TR>
|
* </TABLE>
|
* </TABLE>
|
**************************************************************************/
|
**************************************************************************/
|
void neorv32_uart0_printf(const char *format, ...) {
|
void neorv32_uart0_printf(const char *format, ...) {
|
|
|
char c, string_buf[11];
|
char c, string_buf[11];
|
Line 346... |
Line 350... |
break;
|
break;
|
case 'c': // char
|
case 'c': // char
|
neorv32_uart0_putc((char)va_arg(a, int));
|
neorv32_uart0_putc((char)va_arg(a, int));
|
break;
|
break;
|
case 'i': // 32-bit signed
|
case 'i': // 32-bit signed
|
|
case 'd':
|
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_uart0_putc('-');
|
neorv32_uart0_putc('-');
|
}
|
}
|
Line 359... |
Line 364... |
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_uart0_print(string_buf);
|
neorv32_uart0_print(string_buf);
|
break;
|
break;
|
case 'x': // 32-bit hexadecimal
|
case 'x': // 32-bit hexadecimal
|
|
case 'p':
|
|
case 'X':
|
__neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
|
__neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
|
|
if (c == 'X') {
|
|
__neorv32_uart_touppercase(11, string_buf);
|
|
}
|
neorv32_uart0_print(string_buf);
|
neorv32_uart0_print(string_buf);
|
break;
|
break;
|
default: // unsupported format
|
default: // unsupported format
|
neorv32_uart0_putc('%');
|
neorv32_uart0_putc('%');
|
neorv32_uart0_putc(c);
|
neorv32_uart0_putc(c);
|
Line 463... |
Line 473... |
uint32_t clock = NEORV32_SYSINFO.CLK;
|
uint32_t clock = NEORV32_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
|
|
|
// raw clock prescaler
|
// raw clock prescaler
|
#ifdef make_bootloader
|
#ifndef make_bootloader
|
// use div instructions
|
// use div instructions
|
i = (uint16_t)(clock / (2*baudrate));
|
i = (uint16_t)(clock / (2*baudrate));
|
#else
|
#else
|
// division via repeated subtraction (minimal size, only for bootloader)
|
// division via repeated subtraction (minimal size, only for bootloader)
|
while (clock >= 2*baudrate) {
|
while (clock >= 2*baudrate) {
|
Line 689... |
Line 699... |
* @param[in] format Pointer to format string.
|
* @param[in] format Pointer to format string.
|
*
|
*
|
* <TABLE>
|
* <TABLE>
|
* <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
|
* <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
|
* <TR><TD>%c</TD><TD>Single char</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>%d/%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 - lower-case</TD></TR>
|
|
* <TR><TD>%X</TD><TD>32-bit number, printed as 8-char hexadecimal - upper-case</TD></TR>
|
|
* <TR><TD>%p</TD><TD>32-bit pointer, printed as 8-char hexadecimal - lower-case</TD></TR>
|
* </TABLE>
|
* </TABLE>
|
**************************************************************************/
|
**************************************************************************/
|
void neorv32_uart1_printf(const char *format, ...) {
|
void neorv32_uart1_printf(const char *format, ...) {
|
|
|
char c, string_buf[11];
|
char c, string_buf[11];
|
Line 713... |
Line 725... |
break;
|
break;
|
case 'c': // char
|
case 'c': // char
|
neorv32_uart1_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
|
|
case 'd':
|
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_uart1_putc('-');
|
neorv32_uart1_putc('-');
|
}
|
}
|
Line 726... |
Line 739... |
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_uart1_print(string_buf);
|
neorv32_uart1_print(string_buf);
|
break;
|
break;
|
case 'x': // 32-bit hexadecimal
|
case 'x': // 32-bit hexadecimal
|
|
case 'p':
|
|
case 'X':
|
__neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
|
__neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
|
|
if (c == 'X') {
|
|
__neorv32_uart_touppercase(11, string_buf);
|
|
}
|
neorv32_uart1_print(string_buf);
|
neorv32_uart1_print(string_buf);
|
break;
|
break;
|
default: // unsupported format
|
default: // unsupported format
|
neorv32_uart1_putc('%');
|
neorv32_uart1_putc('%');
|
neorv32_uart1_putc(c);
|
neorv32_uart1_putc(c);
|
Line 852... |
Line 870... |
}
|
}
|
|
|
res[8] = '\0'; // terminate result string
|
res[8] = '\0'; // terminate result string
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|
|
|
|
/**********************************************************************//**
|
|
* Private function to cast a string to UPPERCASE.
|
|
*
|
|
* @param[in] len Total length of input string.
|
|
* @param[in,out] ptr Pointer for input/output string.
|
|
**************************************************************************/
|
|
static void __neorv32_uart_touppercase(uint32_t len, char *ptr) {
|
|
|
|
char tmp;
|
|
|
|
while (len > 0) {
|
|
tmp = *ptr;
|
|
if ((tmp >= 'a') && (tmp <= 'z')) {
|
|
*ptr = tmp - 32;
|
|
}
|
|
ptr++;
|
|
len--;
|
|
}
|
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|