Source code for the Trusted Boot Module.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
tbm-mcu/source/platform/usart.c

250 lines
4.6 KiB

#define _GNU_SOURCE
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/scb.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stddef.h>
#include <limits.h>
#include <sys/types.h>
#include <console.h>
#include <macros.h>
#define CONFIG_USER_ECHO 1
#define RECV_BUF_LEN 128
struct usart_console {
struct console console;
char recv_buf[RECV_BUF_LEN];
volatile size_t cur;
volatile size_t next;
unsigned irq_no;
uint32_t dev;
};
static struct usart_console usart[2];
#ifdef STM32F0
#define USART_STOPBITS_1 USART_CR2_STOP_1_0BIT
#endif
#ifdef STM32F1
#define USART_ISR_RXNE USART_SR_RXNE
#endif
static void usart_isr(struct usart_console *console)
{
size_t i;
if (!console)
return;
while (usart_get_flag(console->dev, USART_ISR_RXNE)) {
console->recv_buf[console->next] = usart_recv(console->dev);
i = (console->next + 1) % RECV_BUF_LEN;
if (i != console->cur)
console->next = i;
}
}
void usart1_isr(void)
{
usart_isr(usart + 0);
}
void usart2_isr(void)
{
usart_isr(usart + 1);
}
int console_peek(char *c, struct console *console_, int block)
{
struct usart_console *console = container_of(console_,
struct usart_console, console);
while (block && console->cur == console->next);
if (console->cur != console->next) {
*c = console->recv_buf[console->cur];
return 0;
}
return -EAGAIN;
}
int console_getc(char *c, struct console *console_)
{
struct usart_console *console = container_of(console_,
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 console *console_, char *buf, size_t n)
{
struct usart_console *console = container_of(console_,
struct usart_console, console);
char *p = buf + strlen(buf);
char c;
*p = '\0';
while (console_getc(&c, console_) == 0) {
switch (c) {
case '\r':
#if CONFIG_USER_ECHO
usart_send_blocking(console->dev, '\r');
usart_send_blocking(console->dev, '\n');
#endif
return 0;
case 10:
case 127:
if (buf < p) {
#if CONFIG_USER_ECHO
usart_send_blocking(console->dev, '\010');
usart_send_blocking(console->dev, ' ');
usart_send_blocking(console->dev, '\010');
#endif
--p;
}
break;
default:
*p = c;
#if CONFIG_USER_ECHO
usart_send_blocking(console->dev, c);
#endif
if (((size_t)p - (size_t)buf) < n) {
++p;
}
}
*p = '\0';
}
*p = '\0';
return -EAGAIN;
}
ssize_t console_read(struct console *console, char *buf, size_t n)
{
char *p = buf;
char c;
while (console_peek(&c, console, 1) == 0) {
switch (c) {
case '\004':
console_getc(&c, console);
return p - buf;
default:
if (((size_t)p - (size_t)buf) >= n)
return p - buf;
*p++ = c;
console_getc(&c, console);
break;
}
}
return p - buf;
}
static ssize_t usart_write(void *cookie, const char *buf, size_t n)
{
struct usart_console *console = cookie;
size_t i;
for (i = 0; i < n; ++i) {
if (buf[i] == '\r')
continue;
if (buf[i] == '\n') {
usart_send_blocking(console->dev, '\r');
}
usart_send_blocking(console->dev, buf[i]);
};
return i;
}
static int usart_get_irq_no(unsigned *irq_no, unsigned dev)
{
if (!irq_no)
return -1;
switch (dev) {
case USART1: *irq_no = NVIC_USART1_IRQ; break;
case USART2: *irq_no = NVIC_USART2_IRQ; break;
default: return -1;
}
return 0;
}
static int usart_init(struct usart_console *console)
{
if (usart_get_irq_no(&console->irq_no, console->dev) < 0)
return -1;
usart_set_baudrate(console->dev, 115200);
usart_set_databits(console->dev, 8);
usart_set_parity(console->dev, USART_PARITY_NONE);
usart_set_stopbits(console->dev, USART_STOPBITS_1);
usart_set_mode(console->dev, USART_MODE_TX_RX);
usart_set_flow_control(console->dev, USART_FLOWCONTROL_NONE);
nvic_enable_irq(console->irq_no);
usart_enable(console->dev);
usart_enable_rx_interrupt(console->dev);
return 0;
}
struct console *console_init(unsigned dev_id)
{
cookie_io_functions_t fops = {
.read = NULL,
.write = usart_write,
.seek = NULL,
.close = NULL,
};
struct usart_console *console;
console = usart + dev_id;
switch (dev_id) {
case 0: console->dev = USART1; break;
case 1: console->dev = USART2; break;
default: return NULL;
}
console->cur = 0;
console->next = 0;
usart_init(console);
console->console.fp = fopencookie(console, "w", fops);
setvbuf(console->console.fp, NULL, _IONBF, 0);
return &console->console;
}