From 9915d1ba46e30990ea149c7a09d1d2ed0d13a331 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Wed, 1 Jun 2016 21:03:05 +0200 Subject: Implement circular buffer UART RX using interrupts. --- projects/cli-test/mgmt-cli.c | 60 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) (limited to 'projects/cli-test/mgmt-cli.c') diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c index 46faae8..abbd999 100644 --- a/projects/cli-test/mgmt-cli.c +++ b/projects/cli-test/mgmt-cli.c @@ -33,10 +33,27 @@ */ #include "stm-init.h" #include "stm-uart.h" +#include "stm-led.h" #include "mgmt-cli.h" #include +extern uint8_t uart_rx; + +struct uart_ringbuf_t { + uint32_t enabled, ridx, widx, overflow; + uint8_t buf[CLI_UART_RECVBUF_SIZE]; +}; + +volatile struct uart_ringbuf_t uart_ringbuf = {1, 0, 0, 0, {0}}; + +#define RINGBUF_RIDX(rb) (rb.ridx & CLI_UART_RECVBUF_MASK) +#define RINGBUF_WIDX(rb) (rb.widx & CLI_UART_RECVBUF_MASK) +#define RINGBUF_COUNT(rb) ((unsigned)(rb.widx - rb.ridx)) +#define RINGBUF_FULL(rb) (RINGBUF_RIDX(rb) == ((rb.widx + 1) & CLI_UART_RECVBUF_MASK)) +#define RINGBUF_READ(rb, dst) {dst = rb.buf[RINGBUF_RIDX(rb)]; rb.buf[RINGBUF_RIDX(rb)] = '.'; rb.ridx++;} +#define RINGBUF_WRITE(rb, src) {rb.buf[RINGBUF_WIDX(rb)] = src; rb.widx++;} + void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf) { char crlf[] = "\r\n"; @@ -46,8 +63,23 @@ void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *bu int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count) { - if (uart_recv_char2(STM_UART_MGMT, buf, count) != HAL_OK) { - return -1; + uint32_t timeout = 0xffffff; + + /* Always explicitly enable the RX interrupt when we get here. + * Prevents us getting stuck waiting for an interrupt that will never come. + */ + __HAL_UART_FLUSH_DRREGISTER(&huart_mgmt); + HAL_UART_Receive_IT(&huart_mgmt, (uint8_t *) &uart_rx, 1); + + while (count && timeout--) { + if (RINGBUF_COUNT(uart_ringbuf)) { + RINGBUF_READ(uart_ringbuf, *(uint8_t *) buf); + buf++; + count--; + } else { + led_toggle(LED_GREEN); + HAL_Delay(10); + } } return 1; } @@ -83,7 +115,11 @@ int embedded_cli_loop(struct cli_def *cli) n = cli_loop_read_next_char(cli, &ctx, &c); - //cli_print(cli, "Next char: '%c' (n == %i)", c, n); + /* + cli_print(cli, "Next char: '%c'/%i, ringbuf ridx %i, widx %i (%i/%i) - count %i", + c, (int) c, uart_ringbuf.ridx, uart_ringbuf.widx, RINGBUF_RIDX(uart_ringbuf), + RINGBUF_WIDX(uart_ringbuf), RINGBUF_COUNT(uart_ringbuf)); + */ if (n == CLI_LOOP_CTRL_BREAK) break; if (n == CLI_LOOP_CTRL_CONTINUE) @@ -98,7 +134,7 @@ int embedded_cli_loop(struct cli_def *cli) if (ctx.l < 0) break; - //cli_print(cli, "Process command: '%s'", ctx.cmd); + /* cli_print(cli, "Process command: '%s'", ctx.cmd); */ n = cli_loop_process_cmd(cli, &ctx); if (n == CLI_LOOP_CTRL_BREAK) break; @@ -107,6 +143,22 @@ int embedded_cli_loop(struct cli_def *cli) return CLI_OK; } +/* Interrupt service routine to be called when data has been received on the MGMT UART. */ +void mgmt_cli_uart_isr(const uint8_t *buf, size_t count) +{ + if (! uart_ringbuf.enabled) return; + + while (count) { + if (RINGBUF_FULL(uart_ringbuf)) { + uart_ringbuf.overflow++; + return; + } + RINGBUF_WRITE(uart_ringbuf, *buf); + buf++; + count--; + } +} + void mgmt_cli_init(struct cli_def *cli) { cli_init(cli); -- cgit v1.2.3