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
9 changed files with 127 additions and 12 deletions
|
@ -13,16 +13,17 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @brief Initialize console_getchar() call.
|
/** @brief Initialize console_getchar()/putchar() calls.
|
||||||
*
|
*
|
||||||
* This function should be called once to initialize pull-style
|
* This function should be called once to initialize pull-style
|
||||||
* access to console via console_getchar() function. This function
|
* access to console via console_getchar() function and buffered
|
||||||
* supersedes, and incompatible with, callback (push-style) console
|
* output using console_putchar() function. This function supercedes,
|
||||||
* handling (via console_input_fn callback, etc.).
|
* and incompatible with, callback (push-style) console handling
|
||||||
|
* (via console_input_fn callback, etc.).
|
||||||
*
|
*
|
||||||
* @return N/A
|
* @return N/A
|
||||||
*/
|
*/
|
||||||
void console_getchar_init(void);
|
void console_init(void);
|
||||||
|
|
||||||
/** @brief Get next char from console input buffer.
|
/** @brief Get next char from console input buffer.
|
||||||
*
|
*
|
||||||
|
@ -38,6 +39,15 @@ void console_getchar_init(void);
|
||||||
*/
|
*/
|
||||||
u8_t console_getchar(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.
|
/** @brief Initialize console_getline() call.
|
||||||
*
|
*
|
||||||
* This function should be called once to initialize pull-style
|
* 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)
|
void main(void)
|
||||||
{
|
{
|
||||||
console_getchar_init();
|
console_init();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
u8_t c = console_getchar();
|
u8_t c = console_getchar();
|
||||||
|
|
|
@ -18,7 +18,7 @@ choice
|
||||||
prompt "Console 'get' function selection"
|
prompt "Console 'get' function selection"
|
||||||
|
|
||||||
config CONSOLE_GETCHAR
|
config CONSOLE_GETCHAR
|
||||||
bool "Character by character input"
|
bool "Character by character input and output"
|
||||||
select UART_CONSOLE_DEBUG_SERVER_HOOKS
|
select UART_CONSOLE_DEBUG_SERVER_HOOKS
|
||||||
select CONSOLE_HANDLER
|
select CONSOLE_HANDLER
|
||||||
|
|
||||||
|
@ -38,6 +38,15 @@ config CONSOLE_GETCHAR_BUFSIZE
|
||||||
default is optimized to save RAM. You may need to increase
|
default is optimized to save RAM. You may need to increase
|
||||||
it e.g. to support large host-side clipboard pastes.
|
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_GETCHAR
|
||||||
|
|
||||||
endif # CONSOLE_PULL
|
endif # CONSOLE_PULL
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
#include <misc/printk.h>
|
#include <misc/printk.h>
|
||||||
|
#include <console.h>
|
||||||
#include <drivers/console/console.h>
|
#include <drivers/console/console.h>
|
||||||
#include <drivers/console/uart_console.h>
|
#include <drivers/console/uart_console.h>
|
||||||
|
|
||||||
|
@ -14,16 +15,58 @@
|
||||||
#error CONFIG_CONSOLE_GETCHAR_BUFSIZE must be power of 2
|
#error CONFIG_CONSOLE_GETCHAR_BUFSIZE must be power of 2
|
||||||
#endif
|
#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 K_SEM_DEFINE(uart_sem, 0, UINT_MAX);
|
||||||
static u8_t uart_ringbuf[CONFIG_CONSOLE_GETCHAR_BUFSIZE];
|
static u8_t uart_ringbuf[CONFIG_CONSOLE_GETCHAR_BUFSIZE];
|
||||||
static u8_t i_get, i_put;
|
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)
|
static int console_irq_input_hook(u8_t c)
|
||||||
{
|
{
|
||||||
int i_next = (i_put + 1) & (CONFIG_CONSOLE_GETCHAR_BUFSIZE - 1);
|
int i_next = (i_put + 1) & (CONFIG_CONSOLE_GETCHAR_BUFSIZE - 1);
|
||||||
|
|
||||||
if (i_next == i_get) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +77,26 @@ static int console_irq_input_hook(u8_t c)
|
||||||
return 1;
|
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)
|
u8_t console_getchar(void)
|
||||||
{
|
{
|
||||||
unsigned int key;
|
unsigned int key;
|
||||||
|
@ -48,9 +111,9 @@ u8_t console_getchar(void)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void console_getchar_init(void)
|
void console_init(void)
|
||||||
{
|
{
|
||||||
uart_console_in_debug_hook_install(console_irq_input_hook);
|
uart_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);
|
||||||
/* All NULLs because we're interested only in the callback above. */
|
uart_irq_callback_set(uart_dev, uart_isr);
|
||||||
uart_register_input(NULL, NULL, NULL);
|
uart_irq_rx_enable(uart_dev);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue