subsys: console: Add buffered output support to console subsystem

Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
Paul Sokolovsky 2017-04-10 10:47:28 +03:00 committed by Anas Nashif
parent 0605fa33ea
commit 3cb13b9687
9 changed files with 127 additions and 12 deletions

View file

@ -13,16 +13,17 @@
extern "C" {
#endif
/** @brief Initialize console_getchar() call.
/** @brief Initialize console_getchar()/putchar() calls.
*
* This function should be called once to initialize pull-style
* access to console via console_getchar() function. This function
* supersedes, and incompatible with, callback (push-style) console
* handling (via console_input_fn callback, etc.).
* access to console via console_getchar() function and buffered
* output using console_putchar() function. This function supercedes,
* and incompatible with, callback (push-style) console handling
* (via console_input_fn callback, etc.).
*
* @return N/A
*/
void console_getchar_init(void);
void console_init(void);
/** @brief Get next char from console input buffer.
*
@ -38,6 +39,15 @@ void console_getchar_init(void);
*/
u8_t console_getchar(void);
/** @brief Output a char to console (buffered).
*
* Puts a character into console output buffer. It will be sent
* to a console asynchronously, e.g. using an IRQ handler.
*
* @return -1 on output buffer overflow, otherwise 0.
*/
int console_putchar(char c);
/** @brief Initialize console_getline() call.
*
* This function should be called once to initialize pull-style

View file

@ -0,0 +1,4 @@
BOARD ?= qemu_x86
CONF_FILE = prj.conf
include ${ZEPHYR_BASE}/Makefile.inc

View file

@ -0,0 +1,4 @@
CONFIG_CONSOLE_PULL=y
CONFIG_CONSOLE_GETCHAR=y
CONFIG_CONSOLE_GETCHAR_BUFSIZE=64
CONFIG_CONSOLE_PUTCHAR_BUFSIZE=512

View file

@ -0,0 +1 @@
obj-y += main.o

View file

@ -0,0 +1,16 @@
#include <zephyr.h>
#include <console.h>
void main(void)
{
console_init();
while (1) {
u8_t c = console_getchar();
console_putchar(c);
if (c == '\r') {
console_putchar('\n');
}
}
}

View file

@ -0,0 +1,8 @@
[test]
tags = samples
build_only = true
# TODO:
# #error "Interrupt not available in uart riscv32-qemu"
# #error "Interrupt-driven Altera JTAG UART not implemented yet"
platform_exclude = qemu_riscv32 qemu_nios2
filter = CONFIG_UART_CONSOLE

View file

@ -4,7 +4,7 @@
void main(void)
{
console_getchar_init();
console_init();
while (1) {
u8_t c = console_getchar();

View file

@ -18,7 +18,7 @@ choice
prompt "Console 'get' function selection"
config CONSOLE_GETCHAR
bool "Character by character input"
bool "Character by character input and output"
select UART_CONSOLE_DEBUG_SERVER_HOOKS
select CONSOLE_HANDLER
@ -38,6 +38,15 @@ config CONSOLE_GETCHAR_BUFSIZE
default is optimized to save RAM. You may need to increase
it e.g. to support large host-side clipboard pastes.
config CONSOLE_PUTCHAR_BUFSIZE
int "console_putchar() buffer size"
default 16
help
Buffer size for console_putchar(). Must be power of 2. The
default is optimized to save RAM. You may need to increase
it e.g. to support large host-side clipboard pastes (with
echo).
endif # CONSOLE_GETCHAR
endif # CONSOLE_PULL

View file

@ -7,6 +7,7 @@
#include <zephyr.h>
#include <uart.h>
#include <misc/printk.h>
#include <console.h>
#include <drivers/console/console.h>
#include <drivers/console/uart_console.h>
@ -14,16 +15,58 @@
#error CONFIG_CONSOLE_GETCHAR_BUFSIZE must be power of 2
#endif
#if CONFIG_CONSOLE_PUTCHAR_BUFSIZE & (CONFIG_CONSOLE_PUTCHAR_BUFSIZE - 1) != 0
#error CONFIG_CONSOLE_PUTCHAR_BUFSIZE must be power of 2
#endif
static K_SEM_DEFINE(uart_sem, 0, UINT_MAX);
static u8_t uart_ringbuf[CONFIG_CONSOLE_GETCHAR_BUFSIZE];
static u8_t i_get, i_put;
static K_SEM_DEFINE(tx_sem, 0, UINT_MAX);
static u8_t tx_ringbuf[CONFIG_CONSOLE_PUTCHAR_BUFSIZE];
static u8_t tx_get, tx_put;
static struct device *uart_dev;
static int console_irq_input_hook(u8_t c);
static void uart_isr(struct device *dev)
{
uart_irq_update(dev);
if (uart_irq_rx_ready(dev)) {
char c;
while (1) {
if (uart_fifo_read(dev, &c, 1) == 0) {
break;
}
console_irq_input_hook(c);
}
}
if (uart_irq_tx_ready(dev)) {
if (tx_get == tx_put) {
/* Output buffer empty, don't bother
* us with tx interrupts
*/
uart_irq_tx_disable(dev);
} else {
uart_fifo_fill(dev, &tx_ringbuf[tx_get++], 1);
tx_get &= CONFIG_CONSOLE_PUTCHAR_BUFSIZE - 1;
}
}
}
static int console_irq_input_hook(u8_t c)
{
int i_next = (i_put + 1) & (CONFIG_CONSOLE_GETCHAR_BUFSIZE - 1);
if (i_next == i_get) {
printk("Console buffer overflow - char dropped\n");
/* Try to give a clue to user that some input was lost */
console_putchar('~');
console_putchar('\n');
return 1;
}
@ -34,6 +77,26 @@ static int console_irq_input_hook(u8_t c)
return 1;
}
int console_putchar(char c)
{
unsigned int key;
int tx_next;
key = irq_lock();
tx_next = (tx_put + 1) & (CONFIG_CONSOLE_PUTCHAR_BUFSIZE - 1);
if (tx_next == tx_get) {
irq_unlock(key);
return -1;
}
tx_ringbuf[tx_put] = c;
tx_put = tx_next;
irq_unlock(key);
uart_irq_tx_enable(uart_dev);
return 0;
}
u8_t console_getchar(void)
{
unsigned int key;
@ -48,9 +111,9 @@ u8_t console_getchar(void)
return c;
}
void console_getchar_init(void)
void console_init(void)
{
uart_console_in_debug_hook_install(console_irq_input_hook);
/* All NULLs because we're interested only in the callback above. */
uart_register_input(NULL, NULL, NULL);
uart_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);
uart_irq_callback_set(uart_dev, uart_isr);
uart_irq_rx_enable(uart_dev);
}