usart: implement interrupt for USART receive

tags/0.1.0
S.J.R. van Schaik 8 years ago
parent 7d0dcfaae5
commit e4d0dc3cb3
  1. 118
      source/drivers/usart_console.c

@ -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;
do {
reg = USART_ISR(console->dev);
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 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;
}
if (buf[i] == '\r') {
buf[i++] = '\n';
putchar('\n');
break;
default:
*p = c;
usart_send_blocking(console->dev, c);
if (((size_t)p - (size_t)buf) < n) {
++p;
}
}
putchar(buf[i]);
*p = '\0';
}
return i;
*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…
Cancel
Save