Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions include/console.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a concern about us removing an API, not sure if we can support a deprecated version or not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was added in very this development cycle, so it was never released. As I mentioned in another comment, the whole "interrupt-driven console" subsystem is authored by me.

void console_init(void);

/** @brief Get next char from console input buffer.
*
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions samples/subsys/console/echo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
BOARD ?= qemu_x86
CONF_FILE = prj.conf

include ${ZEPHYR_BASE}/Makefile.inc
4 changes: 4 additions & 0 deletions samples/subsys/console/echo/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CONFIG_CONSOLE_PULL=y
CONFIG_CONSOLE_GETCHAR=y
CONFIG_CONSOLE_GETCHAR_BUFSIZE=64
CONFIG_CONSOLE_PUTCHAR_BUFSIZE=512
1 change: 1 addition & 0 deletions samples/subsys/console/echo/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj-y += main.o
16 changes: 16 additions & 0 deletions samples/subsys/console/echo/src/main.c
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions samples/subsys/console/echo/testcase.ini
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion samples/subsys/console/getchar/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

void main(void)
{
console_getchar_init();
console_init();

while (1) {
u8_t c = console_getchar();
Expand Down
11 changes: 10 additions & 1 deletion subsys/console/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
73 changes: 68 additions & 5 deletions subsys/console/getchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,66 @@
#include <zephyr.h>
#include <uart.h>
#include <misc/printk.h>
#include <console.h>
#include <drivers/console/console.h>
#include <drivers/console/uart_console.h>

#if CONFIG_CONSOLE_GETCHAR_BUFSIZE & (CONFIG_CONSOLE_GETCHAR_BUFSIZE - 1) != 0
#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;
}

Expand All @@ -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;
Expand All @@ -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);
}