Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
spi_arch.c File Reference

Handling of SPI hardware for STM32. More...

#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/dma.h>
#include "mcu_periph/spi.h"
#include "mcu_periph/gpio.h"
#include <BOARD_CONFIG>
+ Include dependency graph for spi_arch.c:

Go to the source code of this file.

Data Structures

struct  locm3_spi_comm
 Libopencm3 specifc communication parameters for a SPI peripheral in master mode. More...
 
struct  spi_periph_dma
 This structure keeps track of specific config for each SPI bus, which allows for more code reuse. More...
 

Macros

#define NVIC_SPI_IRQ_PRIO   0
 

Functions

static void spi_start_dma_transaction (struct spi_periph *periph, struct spi_transaction *trans)
 Start a new transaction with DMA. More...
 
static void spi_next_transaction (struct spi_periph *periph)
 start next transaction if there is one in the queue More...
 
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)
 
static void process_rx_dma_interrupt (struct spi_periph *periph)
 Processing done after rx completes. More...
 
static void process_tx_dma_interrupt (struct spi_periph *periph)
 Processing done after tx completes. More...
 
static void spi_arch_int_enable (struct spi_periph *spi)
 Enable DMA channel interrupts. More...
 
static void spi_arch_int_disable (struct spi_periph *spi)
 Disable DMA channel interrupts. More...
 
static void SpiSlaveUnselect (uint8_t slave)
 
static void SpiSlaveSelect (uint8_t slave)
 
void spi_slave_select (uint8_t slave)
 Select a slave. More...
 
void spi_slave_unselect (uint8_t slave)
 Unselect a slave. More...
 
void spi_init_slaves (void)
 Initialize all used slaves and unselect them. More...
 
bool spi_submit (struct spi_periph *p, struct spi_transaction *t)
 Submit a spi transaction. More...
 
bool spi_lock (struct spi_periph *p, uint8_t slave)
 Lock the SPI fifo. More...
 
bool spi_resume (struct spi_periph *p, uint8_t slave)
 Resume the SPI fifo. More...
 
static void set_default_comm_config (struct locm3_spi_comm *c)
 
static uint8_t get_transaction_signature (struct spi_transaction *t)
 
static uint8_t get_comm_signature (struct locm3_spi_comm *c)
 
static void set_comm_from_transaction (struct locm3_spi_comm *c, struct spi_transaction *t)
 Update SPI communication conf from generic paparazzi SPI transaction. More...
 
void spi1_arch_init (void)
 Architecture dependent SPI1 initialization. More...
 
void spi2_arch_init (void)
 Architecture dependent SPI2 initialization. More...
 
static void process_slave_tx_dma_interrupt (struct spi_periph *periph)
 SPI_MASTER. More...
 
static void process_slave_rx_dma_interrupt (struct spi_periph *periph)
 
static void spi_slave_set_config (struct spi_periph *periph, struct spi_transaction *trans)
 
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). More...
 

Variables

static struct spi_periph_dma spi1_dma
 
static struct spi_periph_dma spi2_dma
 
process_rx_dma_interruptspi1
 receive transferred over DMA More...
 
process_rx_dma_interruptspi2
 receive transferred over DMA More...
 

Detailed Description

Handling of SPI hardware for STM32.

SPI Master code.

When a transaction is submitted:

  • The transaction is added to the queue if there is space, otherwise it returns false
  • The pending state is set
  • SPI Interrupts (in this case the DMA interrupts) are disabled to prevent race conditions
  • The slave is selected if required, then the before_cb callback is run
  • The spi and dma registers are set up for the specific transaction
  • Spi, DMA and interrupts are enabled and the transaction starts

Obviously output_length and input_length will never both be 0 at the same time. In this case, spi_submit will just return false.

For the DMA and interrupts:

  • If the output_len != input_len, a dummy DMA transfer is triggered for the remainder so the same amount of data is moved in and out. This simplifies keeping the clock going if output_len is greater and allows the rx dma interrupt to represent that the transaction has fully completed.
  • The dummy DMA transfer is initiated at the transaction setup if length is 0, otherwise after the first dma interrupt completes in the ISR directly.
  • The rx DMA transfer completed interrupt marks the end of a complete transaction.
  • The after_cb callback happens BEFORE the slave is unselected as configured.

Definition in file spi_arch.c.


Data Structure Documentation

◆ locm3_spi_comm

struct locm3_spi_comm

Libopencm3 specifc communication parameters for a SPI peripheral in master mode.

Definition at line 76 of file spi_arch.c.

Data Fields
uint32_t br baudrate (clock divider)
uint32_t cpha clock phase
uint32_t cpol clock polarity
uint32_t dff data frame format 8/16 bits
uint32_t lsbfirst frame format lsb/msb first

◆ spi_periph_dma

struct spi_periph_dma

This structure keeps track of specific config for each SPI bus, which allows for more code reuse.

Definition at line 88 of file spi_arch.c.

+ Collaboration diagram for spi_periph_dma:
Data Fields
struct locm3_spi_comm comm current communication parameters
uint8_t comm_sig comm config signature used to check for changes
uint32_t dma DMA controller base address (DMA1 or DMA2)
uint32_t rcc_dma RCC DMA enable clock pin (RCC_DMA1 or RCC_DMA2)
uint8_t rx_chan receive DMA channel (or stream on F4) number
uint32_t rx_chan_sel F4 only: actual receive DMA channel number.
uint16_t rx_dummy_buf dummy rx buffer for receive only cases
bool rx_extra_dummy_dma extra rx dummy dma flag for tx_len > rx_len
uint8_t rx_nvic_irq receive interrupt
uint32_t spi SPI peripheral identifier.
uint32_t spidr SPI DataRegister address for DMA.
uint8_t tx_chan transmit DMA channel (or stream on F4) number
uint32_t tx_chan_sel F4 only: actual transmit DMA channel number.
uint16_t tx_dummy_buf dummy tx buffer for receive only cases
bool tx_extra_dummy_dma extra tx dummy dma flag for tx_len < rx_len
uint8_t tx_nvic_irq transmit interrupt

Macro Definition Documentation

◆ NVIC_SPI_IRQ_PRIO

#define NVIC_SPI_IRQ_PRIO   0

Definition at line 69 of file spi_arch.c.

Function Documentation

◆ get_comm_signature()

◆ get_transaction_signature()

static uint8_t get_transaction_signature ( struct spi_transaction t)
inlinestatic

◆ process_rx_dma_interrupt()

◆ process_slave_rx_dma_interrupt()

void process_slave_rx_dma_interrupt ( struct spi_periph periph)
static

◆ process_slave_tx_dma_interrupt()

void process_slave_tx_dma_interrupt ( struct spi_periph periph)
static

SPI_MASTER.

Definition at line 1721 of file spi_arch.c.

References spi_periph_dma::dma, spi_periph::init_struct, and spi_periph::reg_addr.

◆ process_tx_dma_interrupt()

◆ set_comm_from_transaction()

static void set_comm_from_transaction ( struct locm3_spi_comm c,
struct spi_transaction t 
)
static

◆ set_default_comm_config()

static void set_default_comm_config ( struct locm3_spi_comm c)
static

Definition at line 327 of file spi_arch.c.

References locm3_spi_comm::br, locm3_spi_comm::cpha, locm3_spi_comm::cpol, locm3_spi_comm::dff, and locm3_spi_comm::lsbfirst.

Referenced by spi1_arch_init(), and spi2_arch_init().

+ Here is the caller graph for this function:

◆ spi_arch_int_disable()

static void spi_arch_int_disable ( struct spi_periph spi)
static

Disable DMA channel interrupts.

Definition at line 510 of file spi_arch.c.

References spi_periph_dma::spi.

Referenced by process_slave_rx_dma_interrupt(), spi_lock(), spi_resume(), and spi_submit().

+ Here is the caller graph for this function:

◆ spi_arch_int_enable()

static void spi_arch_int_enable ( struct spi_periph spi)
static

Enable DMA channel interrupts.

Todo:
fix priority levels if necessary

Definition at line 498 of file spi_arch.c.

References NVIC_SPI_IRQ_PRIO, and spi_periph_dma::spi.

Referenced by spi1_arch_init(), spi2_arch_init(), spi_lock(), spi_resume(), spi_slave_register(), and spi_submit().

+ Here is the caller graph for this function:

◆ spi_configure_dma()

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 
)
static

Definition at line 458 of file spi_arch.c.

References spi_periph_dma::dma, spi_periph_dma::rcc_dma, and SPIDss8bit.

Referenced by process_rx_dma_interrupt(), process_tx_dma_interrupt(), spi_slave_register(), and spi_start_dma_transaction().

+ Here is the caller graph for this function:

◆ spi_next_transaction()

static void spi_next_transaction ( struct spi_periph periph)
static

start next transaction if there is one in the queue

Definition at line 517 of file spi_arch.c.

References spi_start_dma_transaction(), SPI_TRANSACTION_QUEUE_LEN, SPIIdle, spi_periph::status, spi_periph::suspend, spi_periph::trans, spi_periph::trans_extract_idx, and spi_periph::trans_insert_idx.

Referenced by process_rx_dma_interrupt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spi_slave_set_config()

static void spi_slave_set_config ( struct spi_periph periph,
struct spi_transaction trans 
)
static

Definition at line 1591 of file spi_arch.c.

References spi_periph_dma::dma, get_transaction_signature(), spi_periph::init_struct, spi_periph::reg_addr, and set_comm_from_transaction().

Referenced by spi_slave_register().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spi_start_dma_transaction()

◆ SpiSlaveSelect()

static void SpiSlaveSelect ( uint8_t  slave)
inlinestatic

◆ SpiSlaveUnselect()

static void SpiSlaveUnselect ( uint8_t  slave)
inlinestatic

Variable Documentation

◆ spi1_dma

struct spi_periph_dma spi1_dma
static

Definition at line 1 of file spi_arch.c.

Referenced by spi1_arch_init().

◆ spi2_dma

struct spi_periph_dma spi2_dma
static

Definition at line 1 of file spi_arch.c.

Referenced by spi2_arch_init().