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;
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);

@ -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;
}

@ -5,13 +5,40 @@
#include <rcc.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)
{
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;
}

Loading…
Cancel
Save