You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/04/13 07:38:57 UTC
[GitHub] andrzej-kaczmarek closed pull request #894: console: Add
asynchronous RX handling for UART
andrzej-kaczmarek closed pull request #894: console: Add asynchronous RX handling for UART
URL: https://github.com/apache/mynewt-core/pull/894
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/sys/console/full/src/console.c b/sys/console/full/src/console.c
index 44cd4c27d..e2251aa3c 100644
--- a/sys/console/full/src/console.c
+++ b/sys/console/full/src/console.c
@@ -515,9 +515,13 @@ console_handle_char(uint8_t byte)
break;
case '\t':
if (completion && !end) {
+#if MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE) == 0
console_blocking_mode();
+#endif
completion(input->line, console_append_char);
+#if MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE) == 0
console_non_blocking_mode();
+#endif
}
break;
}
diff --git a/sys/console/full/src/uart_console.c b/sys/console/full/src/uart_console.c
index 5d708f140..097f1dbc3 100644
--- a/sys/console/full/src/uart_console.c
+++ b/sys/console/full/src/uart_console.c
@@ -30,52 +30,68 @@
#include "console/console.h"
#include "console_priv.h"
-#define CONSOLE_HEAD_INC(cr) (((cr)->cr_head + 1) & ((cr)->cr_size - 1))
-#define CONSOLE_TAIL_INC(cr) (((cr)->cr_tail + 1) & ((cr)->cr_size - 1))
-
static struct uart_dev *uart_dev;
static struct console_ring cr_tx;
-/* must be after console_ring */
static uint8_t cr_tx_buf[MYNEWT_VAL(CONSOLE_UART_TX_BUF_SIZE)];
typedef void (*console_write_char)(struct uart_dev*, uint8_t);
static console_write_char write_char_cb;
-static bool skip_if_tx_full;
+
+#if MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE) > 0
+static struct console_ring cr_rx;
+static uint8_t cr_rx_buf[MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE)];
+
+struct os_event rx_ev;
+#endif
struct console_ring {
- uint8_t cr_head;
- uint8_t cr_tail;
- uint16_t cr_size;
- uint8_t *cr_buf;
+ uint8_t head;
+ uint8_t tail;
+ uint16_t size;
+ uint8_t *buf;
};
+static inline int
+inc_and_wrap(int i, int max)
+{
+ return (i + 1) & (max - 1);
+}
+
static void
-console_add_char(struct console_ring *cr, char ch)
+console_ring_add_char(struct console_ring *cr, char ch)
{
- cr->cr_buf[cr->cr_head] = ch;
- cr->cr_head = CONSOLE_HEAD_INC(cr);
+ cr->buf[cr->head] = ch;
+ cr->head = inc_and_wrap(cr->head, cr->size);
}
static uint8_t
-console_pull_char(struct console_ring *cr)
+console_ring_pull_char(struct console_ring *cr)
{
uint8_t ch;
- ch = cr->cr_buf[cr->cr_tail];
- cr->cr_tail = CONSOLE_TAIL_INC(cr);
+ ch = cr->buf[cr->tail];
+ cr->tail = inc_and_wrap(cr->tail, cr->size);
return ch;
}
+static bool
+console_ring_is_full(const struct console_ring *cr)
+{
+ return inc_and_wrap(cr->head, cr->size) == cr->tail;
+}
+
+static bool
+console_ring_is_empty(const struct console_ring *cr)
+{
+ return cr->head == cr->tail;
+}
+
static void
console_queue_char(struct uart_dev *uart_dev, uint8_t ch)
{
int sr;
OS_ENTER_CRITICAL(sr);
- while (CONSOLE_HEAD_INC(&cr_tx) == cr_tx.cr_tail) {
- if (skip_if_tx_full) {
- OS_EXIT_CRITICAL(sr);
- return;
- }
+ while (console_ring_is_full(&cr_tx)) {
/* TX needs to drain */
uart_start_tx(uart_dev);
OS_EXIT_CRITICAL(sr);
@@ -84,7 +100,7 @@ console_queue_char(struct uart_dev *uart_dev, uint8_t ch)
}
OS_ENTER_CRITICAL(sr);
}
- console_add_char(&cr_tx, ch);
+ console_ring_add_char(&cr_tx, ch);
OS_EXIT_CRITICAL(sr);
}
@@ -98,13 +114,10 @@ console_tx_flush(int cnt)
uint8_t byte;
for (i = 0; i < cnt; i++) {
- if (cr_tx.cr_head == cr_tx.cr_tail) {
- /*
- * Queue is empty.
- */
+ if (console_ring_is_empty(&cr_tx)) {
break;
}
- byte = console_pull_char(&cr_tx);
+ byte = console_ring_pull_char(&cr_tx);
uart_blocking_tx(uart_dev, byte);
}
}
@@ -157,13 +170,10 @@ console_out(int c)
static int
console_tx_char(void *arg)
{
- if (cr_tx.cr_head == cr_tx.cr_tail) {
- /*
- * No more data.
- */
+ if (console_ring_is_empty(&cr_tx)) {
return -1;
}
- return console_pull_char(&cr_tx);
+ return console_ring_pull_char(&cr_tx);
}
/*
@@ -172,13 +182,38 @@ console_tx_char(void *arg)
static int
console_rx_char(void *arg, uint8_t byte)
{
- int rc;
+#if MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE) > 0
+ if (console_ring_is_full(&cr_rx)) {
+ console_ring_pull_char(&cr_rx);
+ }
+
+ console_ring_add_char(&cr_rx, byte);
- skip_if_tx_full = true;
- rc = console_handle_char(byte);
- skip_if_tx_full = false;
- return rc;
+ if (!rx_ev.ev_queued) {
+ os_eventq_put(os_eventq_dflt_get(), &rx_ev);
+ }
+
+ return 0;
+#else
+ return console_handle_char(byte);
+#endif
+}
+
+#if MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE) > 0
+static void
+console_rx_char_event(struct os_event *ev)
+{
+ uint8_t b;
+ int sr;
+
+ while (!console_ring_is_empty(&cr_rx)) {
+ OS_ENTER_CRITICAL(sr);
+ b = console_ring_pull_char(&cr_rx);
+ OS_EXIT_CRITICAL(sr);
+ console_handle_char(b);
+ }
}
+#endif
int
uart_console_is_init(void)
@@ -199,10 +234,17 @@ uart_console_init(void)
.uc_rx_char = console_rx_char,
};
- cr_tx.cr_size = MYNEWT_VAL(CONSOLE_UART_TX_BUF_SIZE);
- cr_tx.cr_buf = cr_tx_buf;
+ cr_tx.size = MYNEWT_VAL(CONSOLE_UART_TX_BUF_SIZE);
+ cr_tx.buf = cr_tx_buf;
write_char_cb = console_queue_char;
+#if MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE) > 0
+ cr_rx.size = MYNEWT_VAL(CONSOLE_UART_RX_BUF_SIZE);
+ cr_rx.buf = cr_rx_buf;
+
+ rx_ev.ev_cb = console_rx_char_event;
+#endif
+
if (!uart_dev) {
uart_dev = (struct uart_dev *)os_dev_open(MYNEWT_VAL(CONSOLE_UART_DEV),
OS_TIMEOUT_NEVER, &uc);
diff --git a/sys/console/full/syscfg.yml b/sys/console/full/syscfg.yml
index 7c1f1f36c..14b47aa6a 100644
--- a/sys/console/full/syscfg.yml
+++ b/sys/console/full/syscfg.yml
@@ -53,6 +53,15 @@ syscfg.defs:
CONSOLE_UART_TX_BUF_SIZE:
description: 'UART console transmit buffer size; must be power of 2.'
value: 32
+ CONSOLE_UART_RX_BUF_SIZE:
+ description: >
+ UART console receive buffer size; must be power of 2.
+ When enabled, data are received to intermediate ringbuffer and
+ processed in task context instead of interrupt. This prevents
+ from possible deadlocking when trying to output large amount of
+ data directly from RX handler (e.g. when echoing data back).
+ Set to 0 to disable (received data are handled in interrupt context)
+ value: 32
CONSOLE_UART_DEV:
description: 'Console UART device.'
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
With regards,
Apache Git Services