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;
|
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 (console->recv_buf[console->next] == '\003')
|
||||||
|
|
||||||
if (next != console->cur)
|
|
||||||
console->next = next;
|
|
||||||
|
|
||||||
if (console->recv_buf[idx] == '\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…
Add table
Add a link
Reference in a new issue