#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #define RECV_BUF_LEN 128 struct usart_console { char recv_buf[RECV_BUF_LEN]; FILE *fp; volatile size_t cur; volatile size_t next; unsigned irq_no; uint32_t dev; }; static struct usart_console usart[4]; static void usart_isr(struct usart_console *console) { size_t i; if (!console) return; while (usart_get_flag(console->dev, USART_ISR_RXNE)) { 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; } } void usart1_isr(void) { usart_isr(usart + 0); } void usart2_isr(void) { usart_isr(usart + 1); } 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; } 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 -EAGAIN; } 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; } break; default: *p = c; usart_send_blocking(console->dev, c); if (((size_t)p - (size_t)buf) < n) { ++p; } } *p = '\0'; } *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) { struct usart_console *console = cookie; size_t i; for (i = 0; i < n; ++i) { if (buf[i] == '\n') usart_send_blocking(console->dev, '\r'); usart_send_blocking(console->dev, buf[i]); }; return i; } static int usart_get_irq_no(unsigned *irq_no, unsigned dev) { if (!irq_no) return -1; switch (dev) { case USART1: *irq_no = NVIC_USART1_IRQ; break; case USART2: *irq_no = NVIC_USART2_IRQ; break; default: return -1; } return 0; } static int usart_init(struct usart_console *console) { if (usart_get_irq_no(&console->irq_no, console->dev) < 0) return -1; usart_set_baudrate(console->dev, 115200); usart_set_databits(console->dev, 8); usart_set_parity(console->dev, USART_PARITY_NONE); usart_set_stopbits(console->dev, USART_CR2_STOP_1_0BIT); usart_set_mode(console->dev, USART_MODE_TX_RX); usart_set_flow_control(console->dev, USART_FLOWCONTROL_NONE); nvic_enable_irq(console->irq_no); usart_enable(console->dev); usart_enable_rx_interrupt(console->dev); return 0; } struct usart_console *console_init(unsigned dev_id) { cookie_io_functions_t fops = { .read = usart_read, .write = usart_write, .seek = NULL, .close = NULL, }; struct usart_console *console; console = usart + dev_id; switch (dev_id) { case 0: console->dev = USART1; break; case 1: console->dev = USART2; break; default: return NULL; } console->cur = 0; console->next = 0; //usart[dev_id] = console; usart_init(console); console->fp = fopencookie(console, "r+w", fops); setbuf(console->fp, NULL); return console; } FILE *console_to_fp(struct usart_console *console) { return console->fp; }