From e4d0dc3cb320e5f0d2e07306bf1462b4fb3284a7 Mon Sep 17 00:00:00 2001 From: "S.J.R. van Schaik" Date: Tue, 18 Jul 2017 12:59:05 +0200 Subject: [PATCH] usart: implement interrupt for USART receive --- source/drivers/usart_console.c | 118 +++++++++++++++++++++++++++++++++++------ 1 file changed, 103 insertions(+), 15 deletions(-) diff --git a/source/drivers/usart_console.c b/source/drivers/usart_console.c index 92aa4f1..65794aa 100644 --- a/source/drivers/usart_console.c +++ b/source/drivers/usart_console.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include @@ -14,36 +16,115 @@ #include -static ssize_t usart_read(void *cookie, char *buf, size_t n) +#define RECV_BUF_LEN 128 + +struct usart_console { + char recv_buf[RECV_BUF_LEN]; + volatile size_t cur, next; + uint32_t dev; +}; + +struct usart_console *usart1 = NULL; +struct usart_console user_console; + +static void usart_isr(struct usart_console *console) { - uint32_t dev = (uint32_t)cookie; + uint32_t reg; size_t i; - for (i = 0; i < n; ++i) { - buf[i] = (char)usart_recv_blocking(dev); + if (!console) + return; + + do { + reg = USART_ISR(console->dev); + + if (!(reg & USART_ISR_RXNE)) + continue; + + console->recv_buf[console->next] = usart_recv(console->dev); + + if (console->recv_buf[console->next] == '\003') + scb_reset_system(); + + i = (console->next + 1) % RECV_BUF_LEN; + + if (i != console->cur) + console->next = i; + } while (usart_get_flag(console->dev, USART_ISR_RXNE)); +} + +void usart1_isr(void) +{ + usart_isr(usart1); +} + +static char usart_getc(struct usart_console *console, int block) +{ + char c = 0; + + while (block && (console->cur == console->next)); + + if (console->cur != console->next) { + c = console->recv_buf[console->cur]; + console->cur = (console->cur + 1) % RECV_BUF_LEN; + } + + return c; +} + +static ssize_t usart_read(void *cookie, char *buf, size_t n) +{ + struct usart_console *console = cookie; + char *p = buf; + char c; + + *buf = '\0'; + + while ((c = usart_getc(console, 1)) != '\r') { + switch (c) { + 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; + } - if (buf[i] == '\r') { - buf[i++] = '\n'; - putchar('\n'); break; + default: + *p = c; + usart_send_blocking(console->dev, c); + + if (((size_t)p - (size_t)buf) < n) { + ++p; + } } - putchar(buf[i]); + *p = '\0'; } - return i; + *p = '\n'; + + if (((size_t)p - (size_t)buf) < n) { + ++p; + } + + *p = '\0'; + + return p - buf; } static ssize_t usart_write(void *cookie, const char *buf, size_t n) { - uint32_t dev = (uint32_t)cookie; + struct usart_console *console = cookie; size_t i; for (i = 0; i < n; ++i) { if (buf[i] == '\n') - usart_send_blocking(dev, '\r'); + usart_send_blocking(console->dev, '\r'); - usart_send_blocking(dev, buf[i]); + usart_send_blocking(console->dev, buf[i]); }; return i; @@ -67,7 +148,10 @@ static void usart_init(void) usart_set_mode(USART1, USART_MODE_TX_RX); usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + nvic_enable_irq(NVIC_USART1_IRQ); + usart_enable(USART1); + usart_enable_rx_interrupt(USART1); } void console_init(void) @@ -85,11 +169,15 @@ void console_init(void) .close = NULL, }; + user_console.dev = USART1; + user_console.cur = 0; + user_console.next = 0; + usart1 = &user_console; usart_init(); - stdin = fopencookie((void *)USART1, "r", console_in); - stdout = fopencookie((void *)USART1, "w", console_out); - stderr = fopencookie((void *)USART1, "w", console_out); + stdin = fopencookie(&user_console, "r", console_in); + stdout = fopencookie(&user_console, "w", console_out); + stderr = fopencookie(&user_console, "w", console_out); setbuf(stdout, NULL); //setlinebuf(stdout);