aboutsummaryrefslogtreecommitdiff
path: root/projects/cli-test
diff options
context:
space:
mode:
authorFredrik Thulin <fredrik@thulin.net>2016-06-01 21:03:05 +0200
committerFredrik Thulin <fredrik@thulin.net>2016-06-01 21:03:05 +0200
commit9915d1ba46e30990ea149c7a09d1d2ed0d13a331 (patch)
tree160f184c1dfc8548de8c6293a5d16376c65ab6ec /projects/cli-test
parent2d08b2038a5cf14a92d8ca3e10fb3421e73e5b74 (diff)
Implement circular buffer UART RX using interrupts.
Diffstat (limited to 'projects/cli-test')
-rw-r--r--projects/cli-test/cli-test.c21
-rw-r--r--projects/cli-test/mgmt-cli.c60
-rw-r--r--projects/cli-test/mgmt-cli.h4
3 files changed, 80 insertions, 5 deletions
diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c
index 26ebbc2..b90d0dd 100644
--- a/projects/cli-test/cli-test.c
+++ b/projects/cli-test/cli-test.c
@@ -49,6 +49,9 @@
extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len);
+/* MGMT UART interrupt receive buffer (data will be put in a larger ring buffer) */
+volatile uint8_t uart_rx;
+
int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc)
{
@@ -286,6 +289,22 @@ void do_early_dfu_jump(void)
while (1);
}
+/* Callback for HAL_UART_Receive_IT(). */
+void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ if (huart->Instance == huart_mgmt.Instance) {
+ mgmt_cli_uart_isr((const uint8_t *) &uart_rx, 1);
+
+ /* Set things up to receive another byte. */
+ HAL_UART_Receive_IT(huart, (uint8_t *) &uart_rx, 1);
+ }
+}
+
+void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
+{
+ led_on(LED_RED);
+ led_on(LED_YELLOW);
+}
int
main()
@@ -318,7 +337,7 @@ main()
/* embedded_cli_loop returns when the user enters 'quit' or 'exit' */
- cli_print(&cli, "Rebooting in 4 seconds");
+ cli_print(&cli, "Rebooting in 3 seconds");
HAL_Delay(3000);
HAL_NVIC_SystemReset();
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 <string.h>
+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);
diff --git a/projects/cli-test/mgmt-cli.h b/projects/cli-test/mgmt-cli.h
index dd6a58b..3b7f503 100644
--- a/projects/cli-test/mgmt-cli.h
+++ b/projects/cli-test/mgmt-cli.h
@@ -68,10 +68,14 @@
cli_register_command2(cli, &cmd_##name##_s, NULL)
+#define CLI_UART_RECVBUF_SIZE 256 /* This must be a power of 2 */
+#define CLI_UART_RECVBUF_MASK (CLI_UART_RECVBUF_SIZE - 1)
+
extern void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf);
extern int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count);
extern int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count);
extern int embedded_cli_loop(struct cli_def *cli);
extern void mgmt_cli_init(struct cli_def *cli);
+extern void mgmt_cli_uart_isr(const uint8_t *buf, size_t count);
#endif /* __STM32_MGMT_CLI_H */