[console][io] Add an optional global input queue.

In this model, getc reads from a global input buffer and the uart posts data to this buffer.

This commit also enables the global input queue for STM32F7 and QEMU-Virt.

Tested on STM32F7/Dartuino and QEMU-ARM A15 with both CONSOLE_HAS_INPUT_BUFFER=1 and CONSOLE_HAS_INPUT_BUFFER=0
This commit is contained in:
Gurjant Kalsi
2016-06-02 15:59:43 -07:00
parent a6ab56cd5f
commit bb4c6402b0
7 changed files with 70 additions and 13 deletions

View File

@@ -28,10 +28,12 @@
#include <assert.h>
#include <list.h>
#include <string.h>
#include <lib/cbuf.h>
#include <arch/ops.h>
#include <platform.h>
#include <platform/debug.h>
#include <kernel/thread.h>
#include <lk/init.h>
/* routines for dealing with main console io */
@@ -44,6 +46,16 @@
static spin_lock_t print_spin_lock = 0;
static struct list_node print_callbacks = LIST_INITIAL_VALUE(print_callbacks);
#if CONSOLE_HAS_INPUT_BUFFER
#ifndef CONSOLE_BUF_LEN
#define CONSOLE_BUF_LEN 256
#endif
/* global input circular buffer */
cbuf_t console_input_cbuf;
static uint8_t console_cbuf_buf[CONSOLE_BUF_LEN];
#endif // CONSOLE_HAS_INPUT_BUFFER
/* print lock must be held when invoking out, outs, outc */
static void out_count(const char *str, size_t len)
{
@@ -100,13 +112,27 @@ static ssize_t __debug_stdio_read(io_handle_t *io, char *s, size_t len)
if (len == 0)
return 0;
#if CONSOLE_HAS_INPUT_BUFFER
ssize_t err = cbuf_read(&console_input_cbuf, s, len, true);
return err;
#else
int err = platform_dgetc(s, true);
if (err < 0)
return err;
return 1;
#endif
}
#if CONSOLE_HAS_INPUT_BUFFER
void console_init_hook(uint level)
{
cbuf_initialize_etc(&console_input_cbuf, sizeof(console_cbuf_buf), console_cbuf_buf);
}
LK_INIT_HOOK(console, console_init_hook, LK_INIT_LEVEL_PLATFORM_EARLY - 1);
#endif
/* global console io handle */
static const io_handle_hooks_t console_io_hooks = {
.write = __debug_stdio_write,
@@ -114,3 +140,4 @@ static const io_handle_hooks_t console_io_hooks = {
};
io_handle_t console_io = IO_HANDLE_INITIAL_VALUE(&console_io_hooks);

View File

@@ -70,5 +70,14 @@ static inline void io_handle_init(io_handle_t *io, io_handle_hooks_t *hooks)
/* the main console io handle */
extern io_handle_t console_io;
#ifndef CONSOLE_HAS_INPUT_BUFFER
#define CONSOLE_HAS_INPUT_BUFFER 0
#endif
#if CONSOLE_HAS_INPUT_BUFFER
/* main input circular buffer that acts as the default input queue */
typedef struct cbuf cbuf_t;
extern cbuf_t console_input_cbuf;
#endif
__END_CDECLS

View File

@@ -3,6 +3,7 @@ LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
MODULE_DEPS := \
lib/cbuf
MODULE_SRCS += \
$(LOCAL_DIR)/console.c \

View File

@@ -37,7 +37,8 @@ MODULE_DEPS += \
GLOBAL_DEFINES += \
MEMBASE=$(MEMBASE) \
MEMSIZE=$(MEMSIZE) \
PLATFORM_SUPPORTS_PANIC_SHELL=1
PLATFORM_SUPPORTS_PANIC_SHELL=1 \
CONSOLE_HAS_INPUT_BUFFER=1
GLOBAL_DEFINES += MMU_WITH_TRAMPOLINE=1 \

View File

@@ -28,6 +28,7 @@
#include <platform/interrupts.h>
#include <platform/debug.h>
#include <platform/qemu-virt.h>
#include <target/debugconfig.h>
/* PL011 implementation */
#define UART_DR (0x00)
@@ -75,14 +76,22 @@ static enum handler_return uart_irq(void *arg)
/* while fifo is not empty, read chars out of it */
while ((UARTREG(base, UART_TFR) & (1<<4)) == 0) {
/* if we're out of rx buffer, mask the irq instead of handling it */
if (cbuf_space_avail(rxbuf) == 0) {
UARTREG(base, UART_IMSC) &= ~(1<<4); // !rxim
break;
}
#if CONSOLE_HAS_INPUT_BUFFER
if (port == DEBUG_UART) {
char c = UARTREG(base, UART_DR);
cbuf_write_char(&console_input_cbuf, c, false);
} else
#endif
{
/* if we're out of rx buffer, mask the irq instead of handling it */
if (cbuf_space_avail(rxbuf) == 0) {
UARTREG(base, UART_IMSC) &= ~(1<<4); // !rxim
break;
}
char c = UARTREG(base, UART_DR);
cbuf_write_char(rxbuf, c, false);
char c = UARTREG(base, UART_DR);
cbuf_write_char(rxbuf, c, false);
}
resched = true;
}

View File

@@ -34,7 +34,8 @@ LK_HEAP_IMPLEMENTATION ?= miniheap
GLOBAL_DEFINES += \
PLATFORM_SUPPORTS_PANIC_SHELL=1 \
NOVM_MAX_ARENAS=2
NOVM_MAX_ARENAS=2 \
CONSOLE_HAS_INPUT_BUFFER=1
MODULE_SRCS += \
$(LOCAL_DIR)/debug.c \

View File

@@ -161,7 +161,7 @@ void uart_init(void)
#endif
}
static void stm32_usart_shared_irq(struct uart_instance *u)
static void stm32_usart_shared_irq(struct uart_instance *u, const unsigned int id)
{
bool resched = false;
@@ -200,7 +200,16 @@ static void stm32_usart_shared_irq(struct uart_instance *u)
/* we got a character */
uint8_t c = (uint8_t)(u->handle.Instance->RDR & 0xff);
if (cbuf_write_char(&u->rx_buf, c, false) != 1) {
cbuf_t *target_buf = &u->rx_buf;
#if CONSOLE_HAS_INPUT_BUFFER
if (id == DEBUG_UART) {
target_buf = &console_input_cbuf;
}
#endif
if (cbuf_write_char(target_buf, c, false) != 1) {
printf("WARNING: uart cbuf overrun!\n");
}
resched = true;
@@ -225,14 +234,14 @@ static void stm32_usart_shared_irq(struct uart_instance *u)
#if ENABLE_UART1
void stm32_USART1_IRQ(void)
{
stm32_usart_shared_irq(uart[1]);
stm32_usart_shared_irq(uart[1], 1);
}
#endif
#if ENABLE_UART3
void stm32_USART3_IRQ(void)
{
stm32_usart_shared_irq(uart[3]);
stm32_usart_shared_irq(uart[3], 3);
}
#endif