subsys: console: Add buffered output support to console subsystem
Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
parent
0605fa33ea
commit
3cb13b9687
|
@ -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
|
||||
|
|
4
samples/subsys/console/echo/Makefile
Normal file
4
samples/subsys/console/echo/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
BOARD ?= qemu_x86
|
||||
CONF_FILE = prj.conf
|
||||
|
||||
include ${ZEPHYR_BASE}/Makefile.inc
|
4
samples/subsys/console/echo/prj.conf
Normal file
4
samples/subsys/console/echo/prj.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
CONFIG_CONSOLE_PULL=y
|
||||
CONFIG_CONSOLE_GETCHAR=y
|
||||
CONFIG_CONSOLE_GETCHAR_BUFSIZE=64
|
||||
CONFIG_CONSOLE_PUTCHAR_BUFSIZE=512
|
1
samples/subsys/console/echo/src/Makefile
Normal file
1
samples/subsys/console/echo/src/Makefile
Normal file
|
@ -0,0 +1 @@
|
|||
obj-y += main.o
|
16
samples/subsys/console/echo/src/main.c
Normal file
16
samples/subsys/console/echo/src/main.c
Normal 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');
|
||||
}
|
||||
}
|
||||
}
|
8
samples/subsys/console/echo/testcase.ini
Normal file
8
samples/subsys/console/echo/testcase.ini
Normal 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
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
void main(void)
|
||||
{
|
||||
console_getchar_init();
|
||||
console_init();
|
||||
|
||||
while (1) {
|
||||
u8_t c = console_getchar();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue