usart: implement interrupt for USART receive
This commit is contained in:
parent
7d0dcfaae5
commit
e4d0dc3cb3
1 changed files with 105 additions and 17 deletions
|
@ -2,6 +2,8 @@
|
|||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
@ -14,36 +16,115 @@
|
|||
|
||||
#include <console.h>
|
||||
|
||||
static ssize_t usart_read(void *cookie, char *buf, size_t n)
|
||||
#define RECV_BUF_LEN 128
|
||||
|
||||
struct usart_console {
|
||||
char recv_buf[RECV_BUF_LEN];
|
||||
volatile size_t cur, next;
|
||||
uint32_t dev;
|
||||
};
|
||||
|
||||
struct usart_console *usart1 = NULL;
|
||||
struct usart_console user_console;
|
||||
|
||||
static void usart_isr(struct usart_console *console)
|
||||
{
|
||||
uint32_t dev = (uint32_t)cookie;
|
||||
uint32_t reg;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
buf[i] = (char)usart_recv_blocking(dev);
|
||||
if (!console)
|
||||
return;
|
||||
|
||||
if (buf[i] == '\r') {
|
||||
buf[i++] = '\n';
|
||||
putchar('\n');
|
||||
break;
|
||||
}
|
||||
do {
|
||||
reg = USART_ISR(console->dev);
|
||||
|
||||
putchar(buf[i]);
|
||||
if (!(reg & USART_ISR_RXNE))
|
||||
continue;
|
||||
|
||||
console->recv_buf[console->next] = usart_recv(console->dev);
|
||||
|
||||
if (console->recv_buf[console->next] == '\003')
|
||||
scb_reset_system();
|
||||
|
||||
i = (console->next + 1) % RECV_BUF_LEN;
|
||||
|
||||
if (i != console->cur)
|
||||
console->next = i;
|
||||
} while (usart_get_flag(console->dev, USART_ISR_RXNE));
|
||||
}
|
||||
|
||||
void usart1_isr(void)
|
||||
{
|
||||
usart_isr(usart1);
|
||||
}
|
||||
|
||||
static char usart_getc(struct usart_console *console, int block)
|
||||
{
|
||||
char c = 0;
|
||||
|
||||
while (block && (console->cur == console->next));
|
||||
|
||||
if (console->cur != console->next) {
|
||||
c = console->recv_buf[console->cur];
|
||||
console->cur = (console->cur + 1) % RECV_BUF_LEN;
|
||||
}
|
||||
|
||||
return i;
|
||||
return c;
|
||||
}
|
||||
|
||||
static ssize_t usart_read(void *cookie, char *buf, size_t n)
|
||||
{
|
||||
struct usart_console *console = cookie;
|
||||
char *p = buf;
|
||||
char c;
|
||||
|
||||
*buf = '\0';
|
||||
|
||||
while ((c = usart_getc(console, 1)) != '\r') {
|
||||
switch (c) {
|
||||
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';
|
||||
}
|
||||
|
||||
*p = '\n';
|
||||
|
||||
if (((size_t)p - (size_t)buf) < n) {
|
||||
++p;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
static ssize_t usart_write(void *cookie, const char *buf, size_t n)
|
||||
{
|
||||
uint32_t dev = (uint32_t)cookie;
|
||||
struct usart_console *console = cookie;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (buf[i] == '\n')
|
||||
usart_send_blocking(dev, '\r');
|
||||
usart_send_blocking(console->dev, '\r');
|
||||
|
||||
usart_send_blocking(dev, buf[i]);
|
||||
usart_send_blocking(console->dev, buf[i]);
|
||||
};
|
||||
|
||||
return i;
|
||||
|
@ -67,7 +148,10 @@ static void usart_init(void)
|
|||
usart_set_mode(USART1, USART_MODE_TX_RX);
|
||||
usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
|
||||
|
||||
nvic_enable_irq(NVIC_USART1_IRQ);
|
||||
|
||||
usart_enable(USART1);
|
||||
usart_enable_rx_interrupt(USART1);
|
||||
}
|
||||
|
||||
void console_init(void)
|
||||
|
@ -85,11 +169,15 @@ void console_init(void)
|
|||
.close = NULL,
|
||||
};
|
||||
|
||||
user_console.dev = USART1;
|
||||
user_console.cur = 0;
|
||||
user_console.next = 0;
|
||||
usart1 = &user_console;
|
||||
usart_init();
|
||||
|
||||
stdin = fopencookie((void *)USART1, "r", console_in);
|
||||
stdout = fopencookie((void *)USART1, "w", console_out);
|
||||
stderr = fopencookie((void *)USART1, "w", console_out);
|
||||
stdin = fopencookie(&user_console, "r", console_in);
|
||||
stdout = fopencookie(&user_console, "w", console_out);
|
||||
stderr = fopencookie(&user_console, "w", console_out);
|
||||
|
||||
setbuf(stdout, NULL);
|
||||
//setlinebuf(stdout);
|
||||
|
|
Loading…
Add table
Reference in a new issue