stm32f0: usart: implement asynchronous serial interfaces

tags/0.1.0
S.J.R. van Schaik 7 years ago
parent ad46f9ccae
commit 7d0f730212
  1. 7
      include/console.h
  2. 99
      source/drivers/usart_console.c
  3. 33
      source/main.c

@ -4,6 +4,7 @@
struct usart_console; struct usart_console;
typedef void (* process_line_func)(FILE *fp); struct usart_console *console_init(unsigned dev_id);
FILE *console_to_fp(struct usart_console *console);
FILE *console_init(unsigned dev_id, process_line_func process_line); int console_getc(char *c, struct usart_console *console);
int console_getline(struct usart_console *console, char *buf, size_t n);

@ -19,46 +19,43 @@
struct usart_console { struct usart_console {
char recv_buf[RECV_BUF_LEN]; char recv_buf[RECV_BUF_LEN];
void (* process_line)(FILE *fp);
FILE *fp; FILE *fp;
volatile size_t cur, next; volatile size_t cur;
volatile size_t next;
unsigned irq_no;
uint32_t dev; uint32_t dev;
}; };
static struct usart_console *usart[4]; static struct usart_console usart[4];
static void usart_isr(struct usart_console *console) static void usart_isr(struct usart_console *console)
{ {
size_t idx, next; size_t i;
if (!console) if (!console)
return; return;
while (usart_get_flag(console->dev, USART_ISR_RXNE)) { while (usart_get_flag(console->dev, USART_ISR_RXNE)) {
idx = console->next; console->recv_buf[console->next] = usart_recv(console->dev);
console->recv_buf[idx] = usart_recv(console->dev);
next = (console->next + 1) % RECV_BUF_LEN;
if (next != console->cur)
console->next = next;
if (console->recv_buf[idx] == '\003') if (console->recv_buf[console->next] == '\003')
scb_reset_system(); scb_reset_system();
if (console->recv_buf[idx] == '\r' && console->process_line) i = (console->next + 1) % RECV_BUF_LEN;
console->process_line(console->fp);
if (i != console->cur)
console->next = i;
} }
} }
void usart1_isr(void) void usart1_isr(void)
{ {
usart_isr(usart[0]); usart_isr(usart + 0);
} }
void usart2_isr(void) void usart2_isr(void)
{ {
usart_isr(usart[1]); usart_isr(usart + 1);
} }
static char usart_getc(struct usart_console *console, int block) 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; 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) static ssize_t usart_read(void *cookie, char *buf, size_t n)
{ {
struct usart_console *console = cookie; 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) static int usart_init(struct usart_console *console)
{ {
unsigned irq_no; if (usart_get_irq_no(&console->irq_no, console->dev) < 0)
if (usart_get_irq_no(&irq_no, console->dev) < 0)
return -1; return -1;
usart_set_baudrate(console->dev, 115200); 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_mode(console->dev, USART_MODE_TX_RX);
usart_set_flow_control(console->dev, USART_FLOWCONTROL_NONE); 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(console->dev);
usart_enable_rx_interrupt(console->dev); usart_enable_rx_interrupt(console->dev);
return 0; 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 = { cookie_io_functions_t fops = {
.read = usart_read, .read = usart_read,
@ -178,8 +224,7 @@ FILE *console_init(unsigned dev_id, void (* process_line)(FILE *fp))
}; };
struct usart_console *console; struct usart_console *console;
if (!(console = malloc(sizeof *console))) console = usart + dev_id;
return NULL;
switch (dev_id) { switch (dev_id) {
case 0: console->dev = USART1; break; 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->cur = 0;
console->next = 0; console->next = 0;
console->process_line = process_line; //usart[dev_id] = console;
usart[dev_id] = console;
usart_init(console); usart_init(console);
@ -198,5 +242,10 @@ FILE *console_init(unsigned dev_id, void (* process_line)(FILE *fp))
setbuf(console->fp, NULL); setbuf(console->fp, NULL);
return console;
}
FILE *console_to_fp(struct usart_console *console)
{
return console->fp; return console->fp;
} }

@ -5,13 +5,40 @@
#include <rcc.h> #include <rcc.h>
#include <shell.h> #include <shell.h>
#include <libopencm3/stm32/usart.h>
struct usart_console *user_con, *admin_con;
FILE *user_io, *admin_io;
char user_line[128];
char admin_line[128];
int main(void) int main(void)
{ {
rcc_init(); rcc_init();
gpio_init(); gpio_init();
console_init(); user_con = console_init(0);
printf("TBM-dev (built on " __DATE__ ")\n"); admin_con = console_init(1);
cmd_loop("tbm # "); 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; return 0;
} }

Loading…
Cancel
Save