stm32f0: usart: implement asynchronous serial interfaces
This commit is contained in:
parent
ad46f9ccae
commit
7d0f730212
3 changed files with 108 additions and 31 deletions
|
@ -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);
|
||||
console->recv_buf[console->next] = 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();
|
||||
|
||||
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…
Add table
Reference in a new issue