From 7d0f730212ba30e283bee9e6b90784534ec67578 Mon Sep 17 00:00:00 2001 From: "S.J.R. van Schaik" Date: Thu, 20 Jul 2017 14:37:07 +0200 Subject: [PATCH] stm32f0: usart: implement asynchronous serial interfaces --- include/console.h | 7 +-- source/drivers/usart_console.c | 99 +++++++++++++++++++++++++++++++----------- source/main.c | 33 ++++++++++++-- 3 files changed, 108 insertions(+), 31 deletions(-) diff --git a/include/console.h b/include/console.h index 99e7997..6c78c74 100644 --- a/include/console.h +++ b/include/console.h @@ -4,6 +4,7 @@ struct usart_console; -typedef void (* process_line_func)(FILE *fp); - -FILE *console_init(unsigned dev_id, process_line_func process_line); +struct usart_console *console_init(unsigned dev_id); +FILE *console_to_fp(struct usart_console *console); +int console_getc(char *c, struct usart_console *console); +int console_getline(struct usart_console *console, char *buf, size_t n); diff --git a/source/drivers/usart_console.c b/source/drivers/usart_console.c index b02df25..1074422 100644 --- a/source/drivers/usart_console.c +++ b/source/drivers/usart_console.c @@ -19,46 +19,43 @@ struct usart_console { char recv_buf[RECV_BUF_LEN]; - void (* process_line)(FILE *fp); FILE *fp; - volatile size_t cur, next; + volatile size_t cur; + volatile size_t next; + unsigned irq_no; uint32_t dev; }; -static struct usart_console *usart[4]; +static struct usart_console usart[4]; static void usart_isr(struct usart_console *console) { - size_t idx, next; + size_t i; if (!console) return; while (usart_get_flag(console->dev, USART_ISR_RXNE)) { - idx = console->next; - console->recv_buf[idx] = usart_recv(console->dev); - - next = (console->next + 1) % RECV_BUF_LEN; - - if (next != console->cur) - console->next = next; + console->recv_buf[console->next] = usart_recv(console->dev); - if (console->recv_buf[idx] == '\003') + if (console->recv_buf[console->next] == '\003') scb_reset_system(); - if (console->recv_buf[idx] == '\r' && console->process_line) - console->process_line(console->fp); + i = (console->next + 1) % RECV_BUF_LEN; + + if (i != console->cur) + console->next = i; } } void usart1_isr(void) { - usart_isr(usart[0]); + usart_isr(usart + 0); } void usart2_isr(void) { - usart_isr(usart[1]); + usart_isr(usart + 1); } static char usart_getc(struct usart_console *console, int block) @@ -75,6 +72,57 @@ static char usart_getc(struct usart_console *console, int block) return c; } +int console_getc(char *c, struct usart_console *console) +{ + if (console->cur == console->next) + return -1; + + if (console->cur != console->next) { + *c = console->recv_buf[console->cur]; + console->cur = (console->cur + 1) % RECV_BUF_LEN; + } + + return 0; +} + +int console_getline(struct usart_console *console, char *buf, size_t n) +{ + char *p = buf + strlen(buf); + char c; + + *p = '\0'; + + while (console_getc(&c, console) == 0) { + switch (c) { + case '\r': + usart_send_blocking(console->dev, '\r'); + usart_send_blocking(console->dev, '\n'); + return 0; + case 10: + case 127: + if (buf < p) { + usart_send_blocking(console->dev, '\010'); + usart_send_blocking(console->dev, ' '); + usart_send_blocking(console->dev, '\010'); + --p; + } + + break; + default: + *p = c; + usart_send_blocking(console->dev, c); + + if (((size_t)p - (size_t)buf) < n) { + ++p; + } + } + + *p = '\0'; + } + + return -E_AGAIN; +} + static ssize_t usart_read(void *cookie, char *buf, size_t n) { struct usart_console *console = cookie; @@ -149,9 +197,7 @@ static int usart_get_irq_no(unsigned *irq_no, unsigned dev) static int usart_init(struct usart_console *console) { - unsigned irq_no; - - if (usart_get_irq_no(&irq_no, console->dev) < 0) + if (usart_get_irq_no(&console->irq_no, console->dev) < 0) return -1; usart_set_baudrate(console->dev, 115200); @@ -161,14 +207,14 @@ static int usart_init(struct usart_console *console) usart_set_mode(console->dev, USART_MODE_TX_RX); usart_set_flow_control(console->dev, USART_FLOWCONTROL_NONE); - nvic_enable_irq(irq_no); + nvic_enable_irq(console->irq_no); usart_enable(console->dev); usart_enable_rx_interrupt(console->dev); return 0; } -FILE *console_init(unsigned dev_id, void (* process_line)(FILE *fp)) +struct usart_console *console_init(unsigned dev_id) { cookie_io_functions_t fops = { .read = usart_read, @@ -178,8 +224,7 @@ FILE *console_init(unsigned dev_id, void (* process_line)(FILE *fp)) }; struct usart_console *console; - if (!(console = malloc(sizeof *console))) - return NULL; + console = usart + dev_id; switch (dev_id) { case 0: console->dev = USART1; break; @@ -189,8 +234,7 @@ FILE *console_init(unsigned dev_id, void (* process_line)(FILE *fp)) console->cur = 0; console->next = 0; - console->process_line = process_line; - usart[dev_id] = console; + //usart[dev_id] = console; usart_init(console); @@ -198,5 +242,10 @@ FILE *console_init(unsigned dev_id, void (* process_line)(FILE *fp)) setbuf(console->fp, NULL); + return console; +} + +FILE *console_to_fp(struct usart_console *console) +{ return console->fp; } diff --git a/source/main.c b/source/main.c index 6d6dbf1..d72e068 100644 --- a/source/main.c +++ b/source/main.c @@ -5,13 +5,40 @@ #include #include +#include + +struct usart_console *user_con, *admin_con; +FILE *user_io, *admin_io; +char user_line[128]; +char admin_line[128]; + int main(void) { rcc_init(); gpio_init(); - console_init(); - printf("TBM-dev (built on " __DATE__ ")\n"); - cmd_loop("tbm # "); + user_con = console_init(0); + admin_con = console_init(1); + user_io = console_to_fp(user_con); + admin_io = console_to_fp(admin_con); + + fprintf(user_io, "TBM-dev (built on " __DATE__ ")\n"); + fprintf(admin_io, "TBM-dev (built on " __DATE__ ")\n"); + fprintf(admin_io, "Welcome to the administrative interface.\n"); + fprintf(user_io, "tbm # "); + + while (1) { + if (console_getline(user_con, user_line, 128) == 0) { + fprintf(user_io, "user: %s\n", user_line); + fprintf(admin_io, "user: %s\n", user_line); + *user_line = '\0'; + } + + if (console_getline(admin_con, admin_line, 128) == 0) { + fprintf(admin_io, "admin: %s\n", admin_line); + fprintf(user_io, "admin: %s\n", admin_line); + *admin_line = '\0'; + } + } return 0; }