54#include <libopencm3/cm3/nvic.h>
55#include <libopencm3/stm32/gpio.h>
56#include <libopencm3/stm32/rcc.h>
57#include <libopencm3/stm32/exti.h>
58#include <libopencm3/stm32/spi.h>
59#include <libopencm3/stm32/dma.h>
68#ifndef NVIC_SPI_IRQ_PRIO
69#define NVIC_SPI_IRQ_PRIO 0
109#error "The STM32 doesn't have SPI0"
266 idx =
p->trans_insert_idx + 1;
268 if ((
idx ==
p->trans_extract_idx) || ((
t->input_length == 0) && (
t->output_length == 0))) {
281 p->trans[
p->trans_insert_idx] =
t;
282 p->trans_insert_idx =
idx;
285 if (
p->status ==
SPIIdle && !
p->suspend) {
308 if (
p->suspend ==
slave + 1) {
311 if (
p->trans_extract_idx !=
p->trans_insert_idx &&
p->status ==
SPIIdle) {
338 return ((
t->dss << 6) | (
t->cdiv << 3) | (
t->bitorder << 2) |
339 (
t->cpha << 1) | (
t->cpol));
554 if (
sig !=
dma->comm_sig) {
564 dma->comm.cpha,
dma->comm.dff,
dma->comm.lsbfirst);
606 dma->rx_extra_dummy_dma =
true;
637 dma->tx_extra_dummy_dma =
true;
710 spi1.trans_insert_idx = 0;
711 spi1.trans_extract_idx = 0;
798 spi2.trans_insert_idx = 0;
799 spi2.trans_extract_idx = 0;
876 spi3_dma.tx_extra_dummy_dma =
false;
878 spi3_dma.rx_extra_dummy_dma =
false;
887 spi3.trans_insert_idx = 0;
888 spi3.trans_extract_idx = 0;
1014#elif defined STM32F4
1034#elif defined STM32F4
1051#elif defined STM32F4
1077#elif defined STM32F4
1100#elif defined STM32F4
1111#elif defined STM32F4
1152#elif defined STM32F4
1174#elif defined STM32F4
1185#elif defined STM32F4
1210#warning "SPI1 slave: Untested code!"
1213#error "Using SPI1 as a slave and master at the same time is not possible."
1228#elif defined STM32F4
1250 spi1.trans_insert_idx = 0;
1251 spi1.trans_extract_idx = 0;
1263#elif defined STM32F4
1305#elif defined STM32F4
1322#elif defined STM32F4
1337#warning "SPI2 slave only tested on STM32F1!"
1341#error "Using SPI2 as a slave and master at the same time is not possible."
1356#elif defined STM32F4
1376 spi2.trans_insert_idx = 0;
1377 spi2.trans_extract_idx = 0;
1389#elif defined STM32F4
1431#elif defined STM32F4
1448#elif defined STM32F4
1463#warning "SPI3 slave only tested on STM32F4!"
1468#error "Using SPI3 as a slave and master at the same time is not possible."
1483#elif defined STM32F4
1494 spi3_dma.tx_extra_dummy_dma =
false;
1496 spi3_dma.rx_extra_dummy_dma =
false;
1505 spi3.trans_insert_idx = 0;
1506 spi3.trans_extract_idx = 0;
1519#elif defined STM32F4
1561#elif defined STM32F4
1578#elif defined STM32F4
1605 dma->comm.cpha,
dma->comm.dff,
dma->comm.lsbfirst);
1636 if (
sig !=
dma->comm_sig) {
1649#elif defined STM32F4
1664#elif defined STM32F4
1678#elif defined STM32F4
1709#elif defined STM32F4
1733#elif defined STM32F4
#define SPI_SELECT_SLAVE3_PIN
#define SPI1_GPIO_AF
SPI Config.
#define SPI1_GPIO_PORT_SCK
#define SPI_SELECT_SLAVE0_PORT
#define SPI_SELECT_SLAVE1_PIN
#define SPI_SELECT_SLAVE4_PORT
#define SPI_SELECT_SLAVE0_PIN
#define SPI1_GPIO_PORT_MISO
#define SPI_SELECT_SLAVE4_PIN
#define SPI_SELECT_SLAVE3_PORT
#define SPI_SELECT_SLAVE1_PORT
#define SPI_SELECT_SLAVE2_PORT
#define SPI_SELECT_SLAVE2_PIN
#define SPI1_GPIO_PORT_MOSI
void gpio_setup_pin_af(ioportid_t port, uint16_t pin, uint8_t af, bool is_output)
Setup a gpio for input or output with alternate function.
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
#define SPI_SELECT_SLAVE5_PIN
#define SPI_SELECT_SLAVE5_PORT
#define SPI2_GPIO_PORT_SCK
#define SPI3_GPIO_PORT_MISO
#define SPI3_GPIO_PORT_SCK
#define SPI2_GPIO_PORT_MOSI
#define SPI3_GPIO_PORT_MOSI
#define SPI2_GPIO_PORT_MISO
#define SPI1_GPIO_PORT_NSS
#define SPI2_GPIO_PORT_NSS
Some architecture independent helper functions for GPIOs.
enum SPISlaveSelect select
slave selection behavior
SPICallback before_cb
NULL or function called before the transaction.
enum SPIStatus status
internal state of the peripheral
SPICallback after_cb
NULL or function called after the transaction.
struct spi_transaction * trans[SPI_TRANSACTION_QUEUE_LEN]
circular buffer holding transactions
enum SPIDataSizeSelect dss
data transfer word size
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
uint16_t input_length
number of data words to read
volatile uint8_t * input_buf
pointer to receive buffer for DMA
volatile uint8_t suspend
control for stop/resume of the fifo
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
uint8_t trans_extract_idx
uint16_t output_length
number of data words to write
enum SPITransactionStatus status
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
bool spi_lock(struct spi_periph *p, uint8_t slave)
spi_lock() function
#define SPI_TRANSACTION_QUEUE_LEN
SPI transaction queue length.
void spi_slave_unselect(uint8_t slave)
spi_slave_unselect() function
void spi1_arch_init(void)
Architecture dependent SPI1 initialization.
SPIDataSizeSelect
SPI data word size of transfer.
process_rx_dma_interrupt & spi2
receive transferred over DMA
bool spi_slave_register(struct spi_periph *periph, struct spi_transaction *trans)
Register a spi transaction in slave mode (only one transaction can be registered).
void spi_slave_select(uint8_t slave)
spi_slave_select() function
void spi2_arch_init(void)
Architecture dependent SPI2 initialization.
process_rx_dma_interrupt & spi1
receive transferred over DMA
bool spi_resume(struct spi_periph *p, uint8_t slave)
spi_resume() function
void spi_init_slaves(void)
spi_init_slaves() function
@ SPICpolIdleLow
CPOL = 0.
@ SPICpolIdleHigh
CPOL = 1.
@ SPISelect
slave is selected before transaction but not unselected
@ SPISelectUnselect
slave is selected before transaction and unselected after
@ SPIUnselect
slave is not selected but unselected after transaction
SPI peripheral structure.
SPI transaction structure.
#define SPI3_GPIO_PORT_NSS
Architecture independent SPI (Serial Peripheral Interface) API.
static uint8_t get_transaction_signature(struct spi_transaction *t)
uint32_t dma
DMA controller base address (DMA1 or DMA2)
uint8_t tx_nvic_irq
transmit interrupt
static uint8_t get_comm_signature(struct locm3_spi_comm *c)
static struct spi_periph_dma spi1_dma
uint16_t rx_dummy_buf
dummy rx buffer for receive only cases
uint8_t tx_chan
transmit DMA channel (or stream on F4) number
struct locm3_spi_comm comm
current communication parameters
static void process_slave_tx_dma_interrupt(struct spi_periph *periph)
SPI_MASTER.
uint32_t dff
data frame format 8/16 bits
static struct spi_periph_dma spi2_dma
static void spi_arch_int_disable(struct spi_periph *spi)
Disable DMA channel interrupts.
static void process_slave_rx_dma_interrupt(struct spi_periph *periph)
static void process_tx_dma_interrupt(struct spi_periph *periph)
Processing done after tx completes.
uint32_t br
baudrate (clock divider)
uint8_t rx_nvic_irq
receive interrupt
uint32_t lsbfirst
frame format lsb/msb first
uint32_t cpol
clock polarity
static void spi_start_dma_transaction(struct spi_periph *periph, struct spi_transaction *_trans)
Start a new transaction with DMA.
#define NVIC_SPI_IRQ_PRIO
uint32_t rx_chan_sel
F4 only: actual receive DMA channel number.
uint32_t spi
SPI peripheral identifier.
static void spi_arch_int_enable(struct spi_periph *spi)
Enable DMA channel interrupts.
static void spi_configure_dma(uint32_t dma, uint32_t rcc_dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr, uint16_t len, enum SPIDataSizeSelect dss, bool increment)
uint16_t tx_dummy_buf
dummy tx buffer for receive only cases
static void spi_next_transaction(struct spi_periph *periph)
start next transaction if there is one in the queue
static void spi_slave_set_config(struct spi_periph *periph, struct spi_transaction *trans)
static void SpiSlaveSelect(uint8_t slave)
bool tx_extra_dummy_dma
extra tx dummy dma flag for tx_len < rx_len
static void set_default_comm_config(struct locm3_spi_comm *c)
uint8_t rx_chan
receive DMA channel (or stream on F4) number
uint8_t comm_sig
comm config signature used to check for changes
uint32_t spidr
SPI DataRegister address for DMA.
static void process_rx_dma_interrupt(struct spi_periph *periph)
Processing done after rx completes.
uint32_t tx_chan_sel
F4 only: actual transmit DMA channel number.
uint32_t rcc_dma
RCC DMA enable clock pin (RCC_DMA1 or RCC_DMA2)
static void set_comm_from_transaction(struct locm3_spi_comm *c, struct spi_transaction *t)
Update SPI communication conf from generic paparazzi SPI transaction.
static void SpiSlaveUnselect(uint8_t slave)
bool rx_extra_dummy_dma
extra rx dummy dma flag for tx_len > rx_len
Libopencm3 specifc communication parameters for a SPI peripheral in master mode.
This structure keeps track of specific config for each SPI bus, which allows for more code reuse.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.