#define _GNU_SOURCE #include /* #include #include #include */ #include #include #include #include #include #include #include #include #include #include #include #define CONFIG_USER_ECHO 1 #define RECV_BUF_LEN 128 struct usart_console { struct console console; char recv_buf[RECV_BUF_LEN]; volatile size_t cur; volatile size_t next; unsigned irq_no; uint32_t dev; }; static struct usart_console usart[2]; #if 0 #ifdef STM32F0 #define USART_STOPBITS_1 USART_CR2_STOP_1_0BIT #endif #ifdef STM32F1 #define USART_ISR_RXNE USART_SR_RXNE #endif #endif void usart_send_blocking(uint32_t dev, char c) { return; } static void usart_isr(struct usart_console *console) { #if 0 size_t i; if (!console) return; while (usart_get_flag(console->dev, USART_ISR_RXNE)) { console->recv_buf[console->next] = usart_recv(console->dev); i = (console->next + 1) % RECV_BUF_LEN; if (i != console->cur) console->next = i; } #endif } void usart1_isr(void) { usart_isr(usart + 0); } void usart2_isr(void) { usart_isr(usart + 1); } int console_peek(char *c, struct console *console_, int block) { struct usart_console *console = container_of(console_, struct usart_console, console); while (block && console->cur == console->next); if (console->cur != console->next) { *c = console->recv_buf[console->cur]; return 0; } return -EAGAIN; } int console_getc(char *c, struct console *console_) { struct usart_console *console = container_of(console_, 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 console *console_, char *buf, size_t n) { struct usart_console *console = container_of(console_, struct usart_console, console); char *p = buf + strlen(buf); char c; *p = '\0'; while (console_getc(&c, console_) == 0) { switch (c) { case '\r': #if CONFIG_USER_ECHO usart_send_blocking(console->dev, '\r'); usart_send_blocking(console->dev, '\n'); #endif return 0; case 10: case 127: if (buf < p) { #if CONFIG_USER_ECHO usart_send_blocking(console->dev, '\010'); usart_send_blocking(console->dev, ' '); usart_send_blocking(console->dev, '\010'); #endif --p; } break; default: *p = c; #if CONFIG_USER_ECHO usart_send_blocking(console->dev, c); #endif if (((size_t)p - (size_t)buf) < n) { ++p; } } *p = '\0'; } *p = '\0'; return -EAGAIN; } ssize_t console_read(struct console *console, char *buf, size_t n) { char *p = buf; char c; while (console_peek(&c, console, 1) == 0) { switch (c) { case '\004': console_getc(&c, console); return p - buf; default: if (((size_t)p - (size_t)buf) >= n) return p - buf; *p++ = c; console_getc(&c, console); break; } } 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] == '\r') continue; 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; #if 0 switch (dev) { case USART1: *irq_no = NVIC_USART1_IRQ; break; case USART2: *irq_no = NVIC_USART2_IRQ; break; default: return -1; } #endif return 0; } static int usart_init(struct usart_console *console) { #if 0 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_STOPBITS_1); 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); #endif return 0; } struct console *console_init(unsigned dev_id) { cookie_io_functions_t fops = { .read = NULL, .write = usart_write, .seek = NULL, .close = NULL, }; struct usart_console *console; console = usart + dev_id; #if 0 switch (dev_id) { case 0: console->dev = USART1; break; case 1: console->dev = USART2; break; default: return NULL; } #endif console->cur = 0; console->next = 0; usart_init(console); console->console.fp = fopencookie(console, "w", fops); setvbuf(console->console.fp, NULL, _IONBF, 0); return &console->console; }