mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-03-16 13:59:13 +00:00
473 lines
18 KiB
C
473 lines
18 KiB
C
/******************************************************************************
|
|
* The MIT License
|
|
*
|
|
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
|
* Copyright (c) 2010 Perry Hung.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* @file libmaple/include/libmaple/spi.h
|
|
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
|
* @brief Serial Peripheral Interface (SPI) and Integrated
|
|
* Interchip Sound (I2S) peripheral support.
|
|
*
|
|
* I2S support is currently limited to register maps and bit definitions.
|
|
*/
|
|
|
|
#ifndef _LIBMAPLE_SPI_H_
|
|
#define _LIBMAPLE_SPI_H_
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <libmaple/libmaple_types.h>
|
|
#include <libmaple/rcc.h>
|
|
#include <libmaple/nvic.h>
|
|
/* Roger clark. Replaced with line below #include <series/spi.h>*/
|
|
#include "stm32f1/include/series/spi.h"
|
|
|
|
|
|
/*
|
|
* Register maps
|
|
*/
|
|
|
|
/** SPI register map type. */
|
|
typedef struct spi_reg_map {
|
|
__io uint32 CR1; /**< Control register 1 */
|
|
__io uint32 CR2; /**< Control register 2 */
|
|
__io uint32 SR; /**< Status register */
|
|
__io uint32 DR; /**< Data register */
|
|
__io uint32 CRCPR; /**< CRC polynomial register */
|
|
__io uint32 RXCRCR; /**< RX CRC register */
|
|
__io uint32 TXCRCR; /**< TX CRC register */
|
|
__io uint32 I2SCFGR; /**< I2S configuration register */
|
|
__io uint32 I2SPR; /**< I2S prescaler register */
|
|
} spi_reg_map;
|
|
|
|
/*
|
|
* Register bit definitions
|
|
*/
|
|
|
|
/* Control register 1 */
|
|
|
|
#define SPI_CR1_BIDIMODE_BIT 15
|
|
#define SPI_CR1_BIDIOE_BIT 14
|
|
#define SPI_CR1_CRCEN_BIT 13
|
|
#define SPI_CR1_CRCNEXT_BIT 12
|
|
#define SPI_CR1_DFF_BIT 11
|
|
#define SPI_CR1_RXONLY_BIT 10
|
|
#define SPI_CR1_SSM_BIT 9
|
|
#define SPI_CR1_SSI_BIT 8
|
|
#define SPI_CR1_LSBFIRST_BIT 7
|
|
#define SPI_CR1_SPE_BIT 6
|
|
#define SPI_CR1_MSTR_BIT 2
|
|
#define SPI_CR1_CPOL_BIT 1
|
|
#define SPI_CR1_CPHA_BIT 0
|
|
|
|
#define SPI_CR1_BIDIMODE (1U << SPI_CR1_BIDIMODE_BIT)
|
|
#define SPI_CR1_BIDIMODE_2_LINE (0x0 << SPI_CR1_BIDIMODE_BIT)
|
|
#define SPI_CR1_BIDIMODE_1_LINE (0x1 << SPI_CR1_BIDIMODE_BIT)
|
|
#define SPI_CR1_BIDIOE (1U << SPI_CR1_BIDIOE_BIT)
|
|
#define SPI_CR1_CRCEN (1U << SPI_CR1_CRCEN_BIT)
|
|
#define SPI_CR1_CRCNEXT (1U << SPI_CR1_CRCNEXT_BIT)
|
|
#define SPI_CR1_DFF (1U << SPI_CR1_DFF_BIT)
|
|
#define SPI_CR1_DFF_8_BIT (0x0 << SPI_CR1_DFF_BIT)
|
|
#define SPI_CR1_DFF_16_BIT (0x1 << SPI_CR1_DFF_BIT)
|
|
#define SPI_CR1_RXONLY (1U << SPI_CR1_RXONLY_BIT)
|
|
#define SPI_CR1_SSM (1U << SPI_CR1_SSM_BIT)
|
|
#define SPI_CR1_SSI (1U << SPI_CR1_SSI_BIT)
|
|
#define SPI_CR1_LSBFIRST (1U << SPI_CR1_LSBFIRST_BIT)
|
|
#define SPI_CR1_SPE (1U << SPI_CR1_SPE_BIT)
|
|
#define SPI_CR1_BR (0x7 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_2 (0x0 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_4 (0x1 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_8 (0x2 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_16 (0x3 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_32 (0x4 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_64 (0x5 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_128 (0x6 << 3)
|
|
#define SPI_CR1_BR_PCLK_DIV_256 (0x7 << 3)
|
|
#define SPI_CR1_MSTR (1U << SPI_CR1_MSTR_BIT)
|
|
#define SPI_CR1_CPOL (1U << SPI_CR1_CPOL_BIT)
|
|
#define SPI_CR1_CPOL_LOW (0x0 << SPI_CR1_CPOL_BIT)
|
|
#define SPI_CR1_CPOL_HIGH (0x1 << SPI_CR1_CPOL_BIT)
|
|
#define SPI_CR1_CPHA (1U << SPI_CR1_CPHA_BIT)
|
|
|
|
/* Control register 2 */
|
|
|
|
#define SPI_CR2_TXEIE_BIT 7
|
|
#define SPI_CR2_RXNEIE_BIT 6
|
|
#define SPI_CR2_ERRIE_BIT 5
|
|
#define SPI_CR2_SSOE_BIT 2
|
|
#define SPI_CR2_TXDMAEN_BIT 1
|
|
#define SPI_CR2_RXDMAEN_BIT 0
|
|
|
|
#define SPI_CR2_TXEIE (1U << SPI_CR2_TXEIE_BIT)
|
|
#define SPI_CR2_RXNEIE (1U << SPI_CR2_RXNEIE_BIT)
|
|
#define SPI_CR2_ERRIE (1U << SPI_CR2_ERRIE_BIT)
|
|
#define SPI_CR2_SSOE (1U << SPI_CR2_SSOE_BIT)
|
|
#define SPI_CR2_TXDMAEN (1U << SPI_CR2_TXDMAEN_BIT)
|
|
#define SPI_CR2_RXDMAEN (1U << SPI_CR2_RXDMAEN_BIT)
|
|
|
|
/* Status register */
|
|
|
|
#define SPI_SR_BSY_BIT 7
|
|
#define SPI_SR_OVR_BIT 6
|
|
#define SPI_SR_MODF_BIT 5
|
|
#define SPI_SR_CRCERR_BIT 4
|
|
#define SPI_SR_UDR_BIT 3
|
|
#define SPI_SR_CHSIDE_BIT 2
|
|
#define SPI_SR_TXE_BIT 1
|
|
#define SPI_SR_RXNE_BIT 0
|
|
|
|
#define SPI_SR_BSY (1U << SPI_SR_BSY_BIT)
|
|
#define SPI_SR_OVR (1U << SPI_SR_OVR_BIT)
|
|
#define SPI_SR_MODF (1U << SPI_SR_MODF_BIT)
|
|
#define SPI_SR_CRCERR (1U << SPI_SR_CRCERR_BIT)
|
|
#define SPI_SR_UDR (1U << SPI_SR_UDR_BIT)
|
|
#define SPI_SR_CHSIDE (1U << SPI_SR_CHSIDE_BIT)
|
|
#define SPI_SR_CHSIDE_LEFT (0x0 << SPI_SR_CHSIDE_BIT)
|
|
#define SPI_SR_CHSIDE_RIGHT (0x1 << SPI_SR_CHSIDE_BIT)
|
|
#define SPI_SR_TXE (1U << SPI_SR_TXE_BIT)
|
|
#define SPI_SR_RXNE (1U << SPI_SR_RXNE_BIT)
|
|
|
|
/* I2S configuration register */
|
|
|
|
#define SPI_I2SCFGR_I2SMOD_BIT 11
|
|
#define SPI_I2SCFGR_I2SE_BIT 10
|
|
#define SPI_I2SCFGR_PCMSYNC_BIT 7
|
|
#define SPI_I2SCFGR_CKPOL_BIT 3
|
|
#define SPI_I2SCFGR_CHLEN_BIT 0
|
|
|
|
#define SPI_I2SCFGR_I2SMOD (1U << SPI_I2SCFGR_I2SMOD_BIT)
|
|
#define SPI_I2SCFGR_I2SMOD_SPI (0x0 << SPI_I2SCFGR_I2SMOD_BIT)
|
|
#define SPI_I2SCFGR_I2SMOD_I2S (0x1 << SPI_I2SCFGR_I2SMOD_BIT)
|
|
#define SPI_I2SCFGR_I2SE (1U << SPI_I2SCFGR_I2SE_BIT)
|
|
#define SPI_I2SCFGR_I2SCFG (0x3 << 8)
|
|
#define SPI_I2SCFGR_I2SCFG_SLAVE_TX (0x0 << 8)
|
|
#define SPI_I2SCFGR_I2SCFG_SLAVE_RX (0x1 << 8)
|
|
#define SPI_I2SCFGR_I2SCFG_MASTER_TX (0x2 << 8)
|
|
#define SPI_I2SCFGR_I2SCFG_MASTER_RX (0x3 << 8)
|
|
#define SPI_I2SCFGR_PCMSYNC (1U << SPI_I2SCFGR_PCMSYNC_BIT)
|
|
#define SPI_I2SCFGR_PCMSYNC_SHORT (0x0 << SPI_I2SCFGR_PCMSYNC_BIT)
|
|
#define SPI_I2SCFGR_PCMSYNC_LONG (0x1 << SPI_I2SCFGR_PCMSYNC_BIT)
|
|
#define SPI_I2SCFGR_I2SSTD (0x3 << 4)
|
|
#define SPI_I2SCFGR_I2SSTD_PHILLIPS (0x0 << 4)
|
|
#define SPI_I2SCFGR_I2SSTD_MSB (0x1 << 4)
|
|
#define SPI_I2SCFGR_I2SSTD_LSB (0x2 << 4)
|
|
#define SPI_I2SCFGR_I2SSTD_PCM (0x3 << 4)
|
|
#define SPI_I2SCFGR_CKPOL (1U << SPI_I2SCFGR_CKPOL_BIT)
|
|
#define SPI_I2SCFGR_CKPOL_LOW (0x0 << SPI_I2SCFGR_CKPOL_BIT)
|
|
#define SPI_I2SCFGR_CKPOL_HIGH (0x1 << SPI_I2SCFGR_CKPOL_BIT)
|
|
#define SPI_I2SCFGR_DATLEN (0x3 << 1)
|
|
#define SPI_I2SCFGR_DATLEN_16_BIT (0x0 << 1)
|
|
#define SPI_I2SCFGR_DATLEN_24_BIT (0x1 << 1)
|
|
#define SPI_I2SCFGR_DATLEN_32_BIT (0x2 << 1)
|
|
#define SPI_I2SCFGR_CHLEN (1U << SPI_I2SCFGR_CHLEN_BIT)
|
|
#define SPI_I2SCFGR_CHLEN_16_BIT (0x0 << SPI_I2SCFGR_CHLEN_BIT)
|
|
#define SPI_I2SCFGR_CHLEN_32_BIT (0x1 << SPI_I2SCFGR_CHLEN_BIT)
|
|
|
|
/* I2S prescaler register */
|
|
|
|
#define SPI_I2SPR_MCKOE_BIT 9
|
|
#define SPI_I2SPR_ODD_BIT 8
|
|
|
|
#define SPI_I2SPR_MCKOE (1U << SPI_I2SPR_MCKOE_BIT)
|
|
#define SPI_I2SPR_ODD (1U << SPI_I2SPR_ODD_BIT)
|
|
#define SPI_I2SPR_I2SDIV 0xFF
|
|
|
|
/*
|
|
* Devices
|
|
*/
|
|
|
|
/** SPI device type */
|
|
typedef struct spi_dev {
|
|
spi_reg_map *regs; /**< Register map */
|
|
rcc_clk_id clk_id; /**< RCC clock information */
|
|
nvic_irq_num irq_num; /**< NVIC interrupt number */
|
|
} spi_dev;
|
|
|
|
/*
|
|
* SPI Convenience functions
|
|
*/
|
|
|
|
void spi_init(spi_dev *dev);
|
|
|
|
struct gpio_dev;
|
|
/**
|
|
* @brief Configure GPIO bit modes for use as a SPI port's pins.
|
|
*
|
|
* @param dev SPI device
|
|
* @param as_master If true, configure as bus master; otherwise, as slave.
|
|
* @param nss_dev NSS pin's GPIO device
|
|
* @param nss_bit NSS pin's GPIO bit on nss_dev
|
|
* @param comm_dev SCK, MISO, MOSI pins' GPIO device
|
|
* @param sck_bit SCK pin's GPIO bit on comm_dev
|
|
* @param miso_bit MISO pin's GPIO bit on comm_dev
|
|
* @param mosi_bit MOSI pin's GPIO bit on comm_dev
|
|
*/
|
|
extern void spi_config_gpios(spi_dev *dev,
|
|
uint8 as_master,
|
|
struct gpio_dev *nss_dev,
|
|
uint8 nss_bit,
|
|
struct gpio_dev *comm_dev,
|
|
uint8 sck_bit,
|
|
uint8 miso_bit,
|
|
uint8 mosi_bit);
|
|
|
|
/**
|
|
* @brief SPI mode configuration.
|
|
*
|
|
* A SPI mode determines a combination of the idle state of the clock
|
|
* line (the clock polarity, or "CPOL"), and which clock edge triggers
|
|
* data capture (the clock phase, or "CPHA").
|
|
*/
|
|
typedef enum spi_mode {
|
|
/** Clock idles low, data captured on rising edge (first transition) */
|
|
SPI_MODE_LOW_RISING = 0,
|
|
/** Clock idles low, data captured on falling edge (second transition) */
|
|
SPI_MODE_LOW_FALLING = 1,
|
|
/** Clock idles high, data captured on falling edge (first transition) */
|
|
SPI_MODE_HIGH_FALLING = 2,
|
|
/** Clock idles high, data captured on rising edge (second transition) */
|
|
SPI_MODE_HIGH_RISING = 3,
|
|
|
|
SPI_MODE_0 = SPI_MODE_LOW_RISING, /**< Same as SPI_MODE_LOW_RISING */
|
|
SPI_MODE_1 = SPI_MODE_LOW_FALLING, /**< Same as SPI_MODE_LOW_FALLING */
|
|
SPI_MODE_2 = SPI_MODE_HIGH_FALLING, /**< Same as SPI_MODE_HIGH_FALLING */
|
|
SPI_MODE_3 = SPI_MODE_HIGH_RISING, /**< Same as SPI_MODE_HIGH_RISING */
|
|
} spi_mode;
|
|
|
|
/**
|
|
* @brief SPI baud rate configuration, as a divisor of f_PCLK, the
|
|
* PCLK clock frequency.
|
|
*/
|
|
typedef enum spi_baud_rate {
|
|
SPI_BAUD_PCLK_DIV_2 = SPI_CR1_BR_PCLK_DIV_2, /**< f_PCLK/2 */
|
|
SPI_BAUD_PCLK_DIV_4 = SPI_CR1_BR_PCLK_DIV_4, /**< f_PCLK/4 */
|
|
SPI_BAUD_PCLK_DIV_8 = SPI_CR1_BR_PCLK_DIV_8, /**< f_PCLK/8 */
|
|
SPI_BAUD_PCLK_DIV_16 = SPI_CR1_BR_PCLK_DIV_16, /**< f_PCLK/16 */
|
|
SPI_BAUD_PCLK_DIV_32 = SPI_CR1_BR_PCLK_DIV_32, /**< f_PCLK/32 */
|
|
SPI_BAUD_PCLK_DIV_64 = SPI_CR1_BR_PCLK_DIV_64, /**< f_PCLK/64 */
|
|
SPI_BAUD_PCLK_DIV_128 = SPI_CR1_BR_PCLK_DIV_128, /**< f_PCLK/128 */
|
|
SPI_BAUD_PCLK_DIV_256 = SPI_CR1_BR_PCLK_DIV_256, /**< f_PCLK/256 */
|
|
} spi_baud_rate;
|
|
|
|
/**
|
|
* @brief SPI initialization flags.
|
|
* @see spi_master_enable()
|
|
* @see spi_slave_enable()
|
|
*/
|
|
typedef enum spi_cfg_flag {
|
|
SPI_BIDIMODE = SPI_CR1_BIDIMODE, /**< Bidirectional mode enable */
|
|
SPI_BIDIOE = SPI_CR1_BIDIOE, /**< Output enable in bidirectional
|
|
mode */
|
|
SPI_CRCEN = SPI_CR1_CRCEN, /**< Cyclic redundancy check (CRC)
|
|
enable */
|
|
SPI_DFF_8_BIT = SPI_CR1_DFF_8_BIT, /**< 8-bit data frame format (this is
|
|
the default) */
|
|
SPI_DFF_16_BIT = SPI_CR1_DFF_16_BIT, /**< 16-bit data frame format */
|
|
SPI_RX_ONLY = SPI_CR1_RXONLY, /**< Receive only */
|
|
SPI_SW_SLAVE = SPI_CR1_SSM, /**< Software slave management */
|
|
SPI_SOFT_SS = SPI_CR1_SSI, /**< Software (internal) slave
|
|
select. This flag only has an
|
|
effect when used in combination
|
|
with SPI_SW_SLAVE. */
|
|
SPI_FRAME_LSB = SPI_CR1_LSBFIRST, /**< LSB-first (little-endian) frame
|
|
format */
|
|
SPI_FRAME_MSB = 0, /**< MSB-first (big-endian) frame
|
|
format (this is the default) */
|
|
} spi_cfg_flag;
|
|
|
|
void spi_master_enable(spi_dev *dev,
|
|
spi_baud_rate baud,
|
|
spi_mode mode,
|
|
uint32 flags);
|
|
|
|
void spi_slave_enable(spi_dev *dev,
|
|
spi_mode mode,
|
|
uint32 flags);
|
|
|
|
uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len);
|
|
|
|
/**
|
|
* @brief Call a function on each SPI port
|
|
* @param fn Function to call.
|
|
*/
|
|
extern void spi_foreach(void (*fn)(spi_dev*));
|
|
|
|
void spi_peripheral_enable(spi_dev *dev);
|
|
void spi_peripheral_disable(spi_dev *dev);
|
|
|
|
void spi_tx_dma_enable(spi_dev *dev);
|
|
void spi_tx_dma_disable(spi_dev *dev);
|
|
|
|
void spi_rx_dma_enable(spi_dev *dev);
|
|
void spi_rx_dma_disable(spi_dev *dev);
|
|
|
|
/**
|
|
* @brief Determine if a SPI peripheral is enabled.
|
|
* @param dev SPI device
|
|
* @return True, if and only if dev's peripheral is enabled.
|
|
*/
|
|
static inline uint8 spi_is_enabled(spi_dev *dev) {
|
|
return dev->regs->CR1 & SPI_CR1_SPE_BIT;
|
|
}
|
|
|
|
/**
|
|
* @brief Disable all SPI peripherals
|
|
*/
|
|
static inline void spi_peripheral_disable_all(void) {
|
|
spi_foreach(spi_peripheral_disable);
|
|
}
|
|
|
|
/** Available SPI interrupts */
|
|
typedef enum spi_interrupt {
|
|
SPI_TXE_INTERRUPT = SPI_CR2_TXEIE, /**< TX buffer empty interrupt */
|
|
SPI_RXNE_INTERRUPT = SPI_CR2_RXNEIE, /**< RX buffer not empty interrupt */
|
|
SPI_ERR_INTERRUPT = SPI_CR2_ERRIE /**<
|
|
* Error interrupt (CRC, overrun,
|
|
* and mode fault errors for SPI;
|
|
* underrun, overrun errors for I2S)
|
|
*/
|
|
} spi_interrupt;
|
|
|
|
/**
|
|
* @brief Mask for all spi_interrupt values
|
|
* @see spi_interrupt
|
|
*/
|
|
#define SPI_INTERRUPTS_ALL (SPI_TXE_INTERRUPT | \
|
|
SPI_RXNE_INTERRUPT | \
|
|
SPI_ERR_INTERRUPT)
|
|
|
|
/**
|
|
* @brief Enable SPI interrupt requests
|
|
* @param dev SPI device
|
|
* @param interrupt_flags Bitwise OR of spi_interrupt values to enable
|
|
* @see spi_interrupt
|
|
*/
|
|
static inline void spi_irq_enable(spi_dev *dev, uint32 interrupt_flags) {
|
|
dev->regs->CR2 |= interrupt_flags;
|
|
nvic_irq_enable(dev->irq_num);
|
|
}
|
|
|
|
/**
|
|
* @brief Disable SPI interrupt requests
|
|
* @param dev SPI device
|
|
* @param interrupt_flags Bitwise OR of spi_interrupt values to disable
|
|
* @see spi_interrupt
|
|
*/
|
|
static inline void spi_irq_disable(spi_dev *dev, uint32 interrupt_flags) {
|
|
dev->regs->CR2 &= ~interrupt_flags;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the data frame format flags with which a SPI port is
|
|
* configured.
|
|
* @param dev SPI device whose data frame format to get.
|
|
* @return SPI_DFF_8_BIT, if dev has an 8-bit data frame format.
|
|
* Otherwise, SPI_DFF_16_BIT.
|
|
*/
|
|
static inline spi_cfg_flag spi_dff(spi_dev *dev) {
|
|
return ((dev->regs->CR1 & SPI_CR1_DFF) == SPI_CR1_DFF_8_BIT ?
|
|
SPI_DFF_8_BIT :
|
|
SPI_DFF_16_BIT);
|
|
}
|
|
|
|
/**
|
|
* @brief Determine whether the device's peripheral receive (RX)
|
|
* register is empty.
|
|
* @param dev SPI device
|
|
* @return true, iff dev's RX register is empty.
|
|
*/
|
|
static inline uint8 spi_is_rx_nonempty(spi_dev *dev) {
|
|
return dev->regs->SR & SPI_SR_RXNE;
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieve the contents of the device's peripheral receive
|
|
* (RX) register.
|
|
*
|
|
* You may only call this function when the RX register is nonempty.
|
|
* Calling this function clears the contents of the RX register.
|
|
*
|
|
* @param dev SPI device
|
|
* @return Contents of dev's peripheral RX register
|
|
* @see spi_is_rx_reg_nonempty()
|
|
*/
|
|
static inline uint16 spi_rx_reg(spi_dev *dev) {
|
|
return (uint16)dev->regs->DR;
|
|
}
|
|
|
|
/**
|
|
* @brief Determine whether the device's peripheral transmit (TX)
|
|
* register is empty.
|
|
* @param dev SPI device
|
|
* @return true, iff dev's TX register is empty.
|
|
*/
|
|
static inline uint8 spi_is_tx_empty(spi_dev *dev) {
|
|
return dev->regs->SR & SPI_SR_TXE;
|
|
}
|
|
|
|
/**
|
|
* @brief Load a value into the device's peripheral transmit (TX) register.
|
|
*
|
|
* You may only call this function when the TX register is empty.
|
|
* Calling this function loads val into the peripheral's TX register.
|
|
* If the device is properly configured, this will initiate a
|
|
* transmission, the completion of which will cause the TX register to
|
|
* be empty again.
|
|
*
|
|
* @param dev SPI device
|
|
* @param val Value to load into the TX register. If the SPI data
|
|
* frame format is 8 bit, the value must be right-aligned.
|
|
* @see spi_is_tx_reg_empty()
|
|
* @see spi_init()
|
|
* @see spi_master_enable()
|
|
* @see spi_slave_enable()
|
|
*/
|
|
static inline void spi_tx_reg(spi_dev *dev, uint16 val) {
|
|
dev->regs->DR = val;
|
|
}
|
|
|
|
/**
|
|
* @brief Determine whether the device's peripheral busy (SPI_SR_BSY)
|
|
* flag is set.
|
|
* @param dev SPI device
|
|
* @return true, iff dev's BSY flag is set.
|
|
*/
|
|
static inline uint8 spi_is_busy(spi_dev *dev) {
|
|
return dev->regs->SR & SPI_SR_BSY;
|
|
}
|
|
|
|
/*
|
|
* I2S convenience functions (TODO)
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|