parent
c7685c1d02
commit
a078de7c9f
@ -0,0 +1,19 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
struct spi_dev; |
||||||
|
|
||||||
|
struct spi_ops { |
||||||
|
int (* set_cs_level)(struct spi_dev *dev, int level); |
||||||
|
int (* tx_rx)(struct spi_dev *dev, void *rx_buf, const void *tx_buf, |
||||||
|
size_t len); |
||||||
|
}; |
||||||
|
|
||||||
|
struct spi_dev { |
||||||
|
struct spi_ops *ops; |
||||||
|
uint32_t dev_id; |
||||||
|
}; |
||||||
|
|
||||||
|
struct spi_dev *spi_probe(void); |
||||||
|
int spi_set_cs_level(struct spi_dev *dev, int level); |
||||||
|
int spi_tx_rx(struct spi_dev *dev, void *rx_buf, const void *tx_buf, |
||||||
|
size_t len); |
@ -0,0 +1,21 @@ |
|||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include <spi.h> |
||||||
|
|
||||||
|
int spi_set_cs_level(struct spi_dev *dev, int level) |
||||||
|
{ |
||||||
|
if (!dev) |
||||||
|
return -1; |
||||||
|
|
||||||
|
return dev->ops->set_cs_level(dev, level); |
||||||
|
} |
||||||
|
|
||||||
|
int spi_tx_rx(struct spi_dev *dev, void *rx_buf, const void *tx_buf, |
||||||
|
size_t len) |
||||||
|
{ |
||||||
|
if (!dev) |
||||||
|
return -1; |
||||||
|
|
||||||
|
return dev->ops->tx_rx(dev, rx_buf, tx_buf, len); |
||||||
|
} |
@ -0,0 +1,94 @@ |
|||||||
|
#define _GNU_SOURCE |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include <libopencm3/stm32/rcc.h> |
||||||
|
#include <libopencm3/stm32/gpio.h> |
||||||
|
#include <libopencm3/stm32/spi.h> |
||||||
|
#include <libopencm3/stm32/usart.h> |
||||||
|
|
||||||
|
#include <spi.h> |
||||||
|
|
||||||
|
static int stm32f0_spi_set_cs_level(struct spi_dev *dev, int level); |
||||||
|
static int stm32f0_spi_tx_rx(struct spi_dev *dev, void *rx_buf, |
||||||
|
const void *tx_buf, size_t len); |
||||||
|
|
||||||
|
static struct spi_ops stm32f0_spi_ops = { |
||||||
|
.set_cs_level = stm32f0_spi_set_cs_level, |
||||||
|
.tx_rx = stm32f0_spi_tx_rx, |
||||||
|
}; |
||||||
|
|
||||||
|
static void stm32f0_spi_init(void) |
||||||
|
{ |
||||||
|
/* Set up clocks for SPI 1 */ |
||||||
|
rcc_clock_setup_in_hsi_out_48mhz(); |
||||||
|
rcc_periph_clock_enable(RCC_GPIOA); |
||||||
|
rcc_periph_clock_enable(RCC_GPIOB); |
||||||
|
rcc_periph_clock_enable(RCC_SPI1); |
||||||
|
|
||||||
|
/* Set up GPIOs for SPI 1 */ |
||||||
|
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4); |
||||||
|
gpio_set(GPIOA, GPIO4); |
||||||
|
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO3 | GPIO4 | GPIO5); |
||||||
|
gpio_set_af(GPIOB, GPIO_AF0, GPIO3 | GPIO4 | GPIO5); |
||||||
|
|
||||||
|
spi_set_master_mode(SPI1); |
||||||
|
spi_set_baudrate_prescaler(SPI1, SPI_CR1_BR_FPCLK_DIV_64); |
||||||
|
spi_set_clock_polarity_0(SPI1); |
||||||
|
spi_set_clock_phase_0(SPI1); |
||||||
|
spi_set_full_duplex_mode(SPI1); |
||||||
|
spi_set_unidirectional_mode(SPI1); /* bidirectional but in 3-wire */ |
||||||
|
spi_set_data_size(SPI1, SPI_CR2_DS_8BIT); |
||||||
|
spi_enable_software_slave_management(SPI1); |
||||||
|
spi_send_msb_first(SPI1); |
||||||
|
spi_set_nss_high(SPI1); |
||||||
|
spi_fifo_reception_threshold_8bit(SPI1); |
||||||
|
SPI_I2SCFGR(SPI1) &= ~SPI_I2SCFGR_I2SMOD; |
||||||
|
spi_enable(SPI1); |
||||||
|
} |
||||||
|
|
||||||
|
struct spi_dev *spi_probe(void) |
||||||
|
{ |
||||||
|
struct spi_dev *dev; |
||||||
|
|
||||||
|
if (!(dev = malloc(sizeof *dev))) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
dev->ops = &stm32f0_spi_ops; |
||||||
|
dev->dev_id = SPI1; |
||||||
|
|
||||||
|
stm32f0_spi_init(); |
||||||
|
|
||||||
|
return dev; |
||||||
|
} |
||||||
|
|
||||||
|
static int stm32f0_spi_set_cs_level(struct spi_dev *dev, int level) |
||||||
|
{ |
||||||
|
(void)dev; |
||||||
|
|
||||||
|
if (level) { |
||||||
|
gpio_set(GPIOA, GPIO4); |
||||||
|
} else { |
||||||
|
gpio_clear(GPIOA, GPIO4); |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int stm32f0_spi_tx_rx(struct spi_dev *dev, void *rx_buf, |
||||||
|
const void *tx_buf, size_t len) |
||||||
|
{ |
||||||
|
char *rx = rx_buf; |
||||||
|
const char *tx = tx_buf; |
||||||
|
size_t i; |
||||||
|
|
||||||
|
for (i = 0; i < len; ++i) { |
||||||
|
spi_send8(dev->dev_id, tx ? *tx++ : 0); |
||||||
|
|
||||||
|
if (rx) { |
||||||
|
*rx++ = spi_read8(dev->dev_id); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
Loading…
Reference in new issue