stm32f1: initial support

This commit is contained in:
S.J.R. van Schaik 2017-08-01 14:37:27 +02:00
parent dc6365c7f8
commit ebd770b957
10 changed files with 696 additions and 1 deletions

View file

@ -0,0 +1,5 @@
obj-y += source/platform/stm32f1/gpio.o
obj-y += source/platform/stm32f1/rcc.o
obj-y += source/platform/stm32f1/rtc.o
obj-y += source/platform/stm32f1/spi.o
obj-y += source/platform/stm32f1/usart.o

View file

@ -0,0 +1,41 @@
#include <libopencm3/stm32/gpio.h>
#include <gpio.h>
int gpio_init(void)
{
/* Set up GPIOs for SPI 1 */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO_SPI1_NSS);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_SPI1_SCK |
GPIO_SPI1_MOSI);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
GPIO_SPI1_MISO);
/*gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4);
gpio_set(GPIOA, GPIO4);
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5 | GPIO6 | GPIO7);
gpio_set_af(GPIOA, GPIO_AF0, GPIO5 | GPIO6 | GPIO7);*/
/* Set up GPIOs for user console (USART 1) */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
/*gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO10);
gpio_set_af(GPIOA, GPIO_AF1, GPIO9 | GPIO10);*/
/* Set up GPIOs for admin console (USART 2) */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
/*gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3);
gpio_set_af(GPIOA, GPIO_AF1, GPIO2 | GPIO3);*/
return 0;
}
void gpio_cleanup(void)
{
}

View file

@ -0,0 +1,19 @@
#include <libopencm3/stm32/rcc.h>
#include <rcc.h>
int rcc_init(void)
{
rcc_periph_clock_enable(RCC_AFIO);
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_SPI1);
rcc_periph_clock_enable(RCC_USART1);
rcc_periph_clock_enable(RCC_USART2);
return 0;
}
void rcc_cleanup(void)
{
}

View file

@ -0,0 +1,42 @@
#include <libopencm3/stm32/pwr.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/rtc.h>
#include <macros.h>
#include <rtc.h>
int rtc_get_time(struct tm *time)
{
time_t unix_time;
if (!time)
return -1;
unix_time = rtc_get_counter_val();
if (!gmtime_r(&unix_time, time))
return -1;
return 0;
}
static int rtc_set_time(struct tm *time)
{
time_t unix_time;
if (!time)
return -1;
unix_time = mktime(time);
rtc_set_counter_val((uint32_t)unix_time);
return 0;
}
int rtc_init(struct tm *time)
{
rtc_auto_awake(RCC_LSI, 0x7fff);
rtc_set_time(time);
return 0;
}

View file

@ -0,0 +1,78 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdlib.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/usart.h>
#include <spi.h>
static int stm32f1_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len,
const void *tx_buf, size_t tx_len);
static struct spi_ops stm32f1_spi_ops = {
.tx_rx = stm32f1_spi_tx_rx,
};
static void stm32f1_spi_init(void)
{
spi_reset(SPI1);
spi_init_master(SPI1,
SPI_CR1_BAUDRATE_FPCLK_DIV_64,
SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
SPI_CR1_CPHA_CLK_TRANSITION_2,
SPI_CR1_DFF_8BIT,
SPI_CR1_MSBFIRST);
spi_enable_software_slave_management(SPI1);
spi_set_nss_high(SPI1);
spi_enable(SPI1);
gpio_set(GPIOA, GPIO_SPI1_NSS);
}
struct spi_dev *spi_probe(void)
{
struct spi_dev *dev;
if (!(dev = malloc(sizeof *dev)))
return NULL;
dev->ops = &stm32f1_spi_ops;
dev->dev_id = SPI1;
stm32f1_spi_init();
return dev;
}
void spi_release(struct spi_dev *dev)
{
free(dev);
}
static int stm32f1_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len,
const void *tx_buf, size_t tx_len)
{
char *rx = rx_buf;
const char *tx = tx_buf;
size_t i;
gpio_clear(GPIOA, GPIO_SPI1_NSS);
for (i = 0; i < tx_len; ++i) {
spi_send(dev->dev_id, *tx++);
(void)spi_read(dev->dev_id);
}
if (rx_buf) {
for (i = 0; i < rx_len; ++i) {
spi_send(dev->dev_id, 0);
*rx++ = spi_read(dev->dev_id);
}
}
gpio_set(GPIOA, GPIO_SPI1_NSS);
return 0;
}

View file

@ -0,0 +1,321 @@
#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 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];
static void usart_isr(struct usart_console *console)
{
size_t i;
if (!console)
return;
while (usart_get_flag(console->dev, USART_SR_RXNE)) {
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;
}
}
void usart1_isr(void)
{
usart_isr(usart + 0);
}
void usart2_isr(void)
{
usart_isr(usart + 1);
}
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;
}
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':
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';
}
*p = '\0';
return -EAGAIN;
}
ssize_t console_read(struct console *console_, char *buf, size_t n)
{
struct usart_console *console = container_of(console_,
struct usart_console, console);
char *p = buf;
char c;
*buf = '\0';
while (console_peek(&c, console_, 1) == 0) {
switch (c) {
case '\004':
if (buf < p)
goto out;
console_getc(&c, console_);
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;
}
console_getc(&c, console_);
break;
case '\r':
if (((size_t)p - (size_t)buf) >= n)
goto out;
*p++ = '\n';
usart_send_blocking(console->dev, '\r');
console_getc(&c, console_);
goto out;
default:
if (((size_t)p - (size_t)buf) >= n)
goto out;
*p++ = c;
usart_send_blocking(console->dev, c);
console_getc(&c, console_);
break;
}
}
out:
*p = '\0';
return p - buf;
}
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)
{
struct usart_console *console = cookie;
size_t i;
for (i = 0; i < n; ++i) {
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 = usart_read,
.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, "r+w", fops);
setvbuf(console->console.fp, NULL, _IONBF, 0);
return &console->console;
}