aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmaple/include/libmaple/spi.h118
-rw-r--r--libmaple/rules.mk2
-rw-r--r--libmaple/spi.c77
-rw-r--r--libmaple/stm32f1/include/series/spi.h70
-rw-r--r--libmaple/stm32f1/rules.mk1
-rw-r--r--libmaple/stm32f1/spi.c97
6 files changed, 231 insertions, 134 deletions
diff --git a/libmaple/include/libmaple/spi.h b/libmaple/include/libmaple/spi.h
index 7a665db..5b045a9 100644
--- a/libmaple/include/libmaple/spi.h
+++ b/libmaple/include/libmaple/spi.h
@@ -44,8 +44,7 @@ extern "C" {
#include <libmaple/libmaple_types.h>
#include <libmaple/rcc.h>
#include <libmaple/nvic.h>
-#include <libmaple/gpio.h>
-#include <libmaple/util.h>
+#include <series/spi.h>
/*
* Register maps
@@ -64,13 +63,6 @@ typedef struct spi_reg_map {
__io uint32 I2SPR; /**< I2S prescaler register */
} spi_reg_map;
-/** SPI1 register map base pointer */
-#define SPI1_BASE ((struct spi_reg_map*)0x40013000)
-/** SPI2 register map base pointer */
-#define SPI2_BASE ((struct spi_reg_map*)0x40003800)
-/** SPI3 register map base pointer */
-#define SPI3_BASE ((struct spi_reg_map*)0x40003C00)
-
/*
* Register bit definitions
*/
@@ -91,20 +83,20 @@ typedef struct spi_reg_map {
#define SPI_CR1_CPOL_BIT 1
#define SPI_CR1_CPHA_BIT 0
-#define SPI_CR1_BIDIMODE BIT(SPI_CR1_BIDIMODE_BIT)
+#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 BIT(SPI_CR1_BIDIOE_BIT)
-#define SPI_CR1_CRCEN BIT(SPI_CR1_CRCEN_BIT)
-#define SPI_CR1_CRCNEXT BIT(SPI_CR1_CRCNEXT_BIT)
-#define SPI_CR1_DFF BIT(SPI_CR1_DFF_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 BIT(SPI_CR1_RXONLY_BIT)
-#define SPI_CR1_SSM BIT(SPI_CR1_SSM_BIT)
-#define SPI_CR1_SSI BIT(SPI_CR1_SSI_BIT)
-#define SPI_CR1_LSBFIRST BIT(SPI_CR1_LSBFIRST_BIT)
-#define SPI_CR1_SPE BIT(SPI_CR1_SPE_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)
@@ -114,17 +106,14 @@ typedef struct spi_reg_map {
#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 BIT(SPI_CR1_MSTR_BIT)
-#define SPI_CR1_CPOL BIT(SPI_CR1_CPOL_BIT)
+#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 BIT(SPI_CR1_CPHA_BIT)
+#define SPI_CR1_CPHA (1U << SPI_CR1_CPHA_BIT)
/* Control register 2 */
-/* RM0008-ism: SPI CR2 has "TXDMAEN" and "RXDMAEN" bits, while the
- * USARTs have CR3 "DMAR" and "DMAT" bits. */
-
#define SPI_CR2_TXEIE_BIT 7
#define SPI_CR2_RXNEIE_BIT 6
#define SPI_CR2_ERRIE_BIT 5
@@ -132,12 +121,12 @@ typedef struct spi_reg_map {
#define SPI_CR2_TXDMAEN_BIT 1
#define SPI_CR2_RXDMAEN_BIT 0
-#define SPI_CR2_TXEIE BIT(SPI_CR2_TXEIE_BIT)
-#define SPI_CR2_RXNEIE BIT(SPI_CR2_RXNEIE_BIT)
-#define SPI_CR2_ERRIE BIT(SPI_CR2_ERRIE_BIT)
-#define SPI_CR2_SSOE BIT(SPI_CR2_SSOE_BIT)
-#define SPI_CR2_TXDMAEN BIT(SPI_CR2_TXDMAEN_BIT)
-#define SPI_CR2_RXDMAEN BIT(SPI_CR2_RXDMAEN_BIT)
+#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 */
@@ -150,37 +139,35 @@ typedef struct spi_reg_map {
#define SPI_SR_TXE_BIT 1
#define SPI_SR_RXNE_BIT 0
-#define SPI_SR_BSY BIT(SPI_SR_BSY_BIT)
-#define SPI_SR_OVR BIT(SPI_SR_OVR_BIT)
-#define SPI_SR_MODF BIT(SPI_SR_MODF_BIT)
-#define SPI_SR_CRCERR BIT(SPI_SR_CRCERR_BIT)
-#define SPI_SR_UDR BIT(SPI_SR_UDR_BIT)
-#define SPI_SR_CHSIDE BIT(SPI_SR_CHSIDE_BIT)
+#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 BIT(SPI_SR_TXE_BIT)
-#define SPI_SR_RXNE BIT(SPI_SR_RXNE_BIT)
+#define SPI_SR_TXE (1U << SPI_SR_TXE_BIT)
+#define SPI_SR_RXNE (1U << SPI_SR_RXNE_BIT)
/* I2S configuration register */
-/* RM0008-ism: CR1 has "CPOL", I2SCFGR has "CKPOL". */
-
#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 BIT(SPI_I2SCFGR_I2SMOD_BIT)
+#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 BIT(SPI_I2SCFGR_I2SE_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 BIT(SPI_I2SCFGR_PCMSYNC_BIT)
+#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)
@@ -188,17 +175,26 @@ typedef struct spi_reg_map {
#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 BIT(SPI_I2SCFGR_CKPOL_BIT)
+#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 BIT(SPI_I2SCFGR_CHLEN_BIT)
+#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
*/
@@ -210,22 +206,28 @@ typedef struct spi_dev {
nvic_irq_num irq_num; /**< NVIC interrupt number */
} spi_dev;
-extern spi_dev *SPI1;
-extern spi_dev *SPI2;
-#ifdef STM32_HIGH_DENSITY
-extern spi_dev *SPI3;
-#endif
-
/*
* 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 as_master If true, configure bits for use as a bus master.
+ * Otherwise, configure bits for use as slave.
+ * @param nss_dev NSS pin's GPIO device
+ * @param comm_dev SCK, MISO, MOSI pins' GPIO device
+ * @param nss_bit NSS pin's GPIO bit on nss_dev
+ * @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
+ */
void spi_gpio_cfg(uint8 as_master,
- gpio_dev *nss_dev,
+ struct gpio_dev *nss_dev,
uint8 nss_bit,
- gpio_dev *comm_dev,
+ struct gpio_dev *comm_dev,
uint8 sck_bit,
uint8 miso_bit,
uint8 mosi_bit);
@@ -244,7 +246,7 @@ typedef enum spi_mode {
clock transition */
SPI_MODE_2, /**< Clock line idles high (1), data capture on first
clock transition. */
- SPI_MODE_3 /**< Clock line idles high (1), data capture on
+ SPI_MODE_3, /**< Clock line idles high (1), data capture on
second clock transition. */
} spi_mode;
@@ -300,7 +302,11 @@ void spi_slave_enable(spi_dev *dev,
uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len);
-void spi_foreach(void (*fn)(spi_dev (*dev)));
+/**
+ * @brief Call a function on each SPI port
+ * @param fn Function to call.
+ */
+void spi_foreach(void (*fn)(spi_dev*));
void spi_peripheral_enable(spi_dev *dev);
void spi_peripheral_disable(spi_dev *dev);
diff --git a/libmaple/rules.mk b/libmaple/rules.mk
index 2f5e066..93716d2 100644
--- a/libmaple/rules.mk
+++ b/libmaple/rules.mk
@@ -18,6 +18,7 @@ cSRCS_$(d) += iwdg.c
cSRCS_$(d) += nvic.c
cSRCS_$(d) += pwr.c
cSRCS_$(d) += rcc.c
+cSRCS_$(d) += spi.c
cSRCS_$(d) += syscalls.c
cSRCS_$(d) += systick.c
cSRCS_$(d) += timer.c
@@ -29,7 +30,6 @@ cSRCS_$(d) += util.c
# cSRCS_$(d) += dma.c
# cSRCS_$(d) += exti.c
# cSRCS_$(d) += i2c.c
-# cSRCS_$(d) += spi.c
sSRCS_$(d) := exc.S
diff --git a/libmaple/spi.c b/libmaple/spi.c
index 00b7ce2..194a82e 100644
--- a/libmaple/spi.c
+++ b/libmaple/spi.c
@@ -38,36 +38,6 @@
static void spi_reconfigure(spi_dev *dev, uint32 cr1_config);
/*
- * SPI devices
- */
-
-static spi_dev spi1 = {
- .regs = SPI1_BASE,
- .clk_id = RCC_SPI1,
- .irq_num = NVIC_SPI1,
-};
-/** SPI device 1 */
-spi_dev *SPI1 = &spi1;
-
-static spi_dev spi2 = {
- .regs = SPI2_BASE,
- .clk_id = RCC_SPI2,
- .irq_num = NVIC_SPI2,
-};
-/** SPI device 2 */
-spi_dev *SPI2 = &spi2;
-
-#ifdef STM32_HIGH_DENSITY
-static spi_dev spi3 = {
- .regs = SPI3_BASE,
- .clk_id = RCC_SPI3,
- .irq_num = NVIC_SPI3,
-};
-/** SPI device 3 */
-spi_dev *SPI3 = &spi3;
-#endif
-
-/*
* SPI convenience routines
*/
@@ -81,37 +51,6 @@ void spi_init(spi_dev *dev) {
}
/**
- * @brief Configure GPIO bit modes for use as a SPI port's pins.
- * @param as_master If true, configure bits for use as a bus master.
- * Otherwise, configure bits for use as slave.
- * @param nss_dev NSS pin's GPIO device
- * @param comm_dev SCK, MISO, MOSI pins' GPIO device
- * @param nss_bit NSS pin's GPIO bit on nss_dev
- * @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
- */
-void spi_gpio_cfg(uint8 as_master,
- gpio_dev *nss_dev,
- uint8 nss_bit,
- gpio_dev *comm_dev,
- uint8 sck_bit,
- uint8 miso_bit,
- uint8 mosi_bit) {
- if (as_master) {
- gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP);
- gpio_set_mode(comm_dev, sck_bit, GPIO_AF_OUTPUT_PP);
- gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING);
- gpio_set_mode(comm_dev, mosi_bit, GPIO_AF_OUTPUT_PP);
- } else {
- gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING);
- gpio_set_mode(comm_dev, sck_bit, GPIO_INPUT_FLOATING);
- gpio_set_mode(comm_dev, miso_bit, GPIO_AF_OUTPUT_PP);
- gpio_set_mode(comm_dev, mosi_bit, GPIO_INPUT_FLOATING);
- }
-}
-
-/**
* @brief Configure and enable a SPI device as bus master.
*
* The device's peripheral will be disabled before being reconfigured.
@@ -166,18 +105,6 @@ uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) {
}
/**
- * @brief Call a function on each SPI port
- * @param fn Function to call.
- */
-void spi_foreach(void (*fn)(spi_dev*)) {
- fn(SPI1);
- fn(SPI2);
-#ifdef STM32_HIGH_DENSITY
- fn(SPI3);
-#endif
-}
-
-/**
* @brief Enable a SPI peripheral
* @param dev Device to enable
*/
@@ -235,7 +162,3 @@ static void spi_reconfigure(spi_dev *dev, uint32 cr1_config) {
dev->regs->CR1 = cr1_config;
spi_peripheral_enable(dev);
}
-
-/*
- * IRQ handlers (TODO)
- */
diff --git a/libmaple/stm32f1/include/series/spi.h b/libmaple/stm32f1/include/series/spi.h
new file mode 100644
index 0000000..167df0c
--- /dev/null
+++ b/libmaple/stm32f1/include/series/spi.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * 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/stm32f1/include/series/spi.h
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F1 SPI/I2S series header.
+ */
+
+#ifndef _LIBMAPLE_STM32F1_SPI_H_
+#define _LIBMAPLE_STM32F1_SPI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Register map base pointers
+ */
+
+struct spi_reg_map;
+
+/** SPI1 register map base pointer */
+#define SPI1_BASE ((struct spi_reg_map*)0x40013000)
+/** SPI2 register map base pointer */
+#define SPI2_BASE ((struct spi_reg_map*)0x40003800)
+/** SPI3 register map base pointer */
+#define SPI3_BASE ((struct spi_reg_map*)0x40003C00)
+
+/*
+ * Device pointers
+ */
+
+struct spi_dev;
+
+extern struct spi_dev *SPI1;
+extern struct spi_dev *SPI2;
+#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
+extern struct spi_dev *SPI3;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/stm32f1/rules.mk b/libmaple/stm32f1/rules.mk
index 03fddb3..52ceea6 100644
--- a/libmaple/stm32f1/rules.mk
+++ b/libmaple/stm32f1/rules.mk
@@ -16,6 +16,7 @@ cSRCS_$(d) += bkp.c
cSRCS_$(d) += fsmc.c
cSRCS_$(d) += gpio.c
cSRCS_$(d) += rcc.c
+cSRCS_$(d) += spi.c
cSRCS_$(d) += timer.c
cSRCS_$(d) += usart.c
diff --git a/libmaple/stm32f1/spi.c b/libmaple/stm32f1/spi.c
new file mode 100644
index 0000000..b860918
--- /dev/null
+++ b/libmaple/stm32f1/spi.c
@@ -0,0 +1,97 @@
+/******************************************************************************
+ * 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/stm32f1/spi.c
+ * @author Marti Bolivar <mbolivar@leaflabs.com>
+ * @brief STM32F1 SPI/I2S support.
+ */
+
+#include <libmaple/spi.h>
+#include <libmaple/gpio.h>
+
+/*
+ * Devices
+ */
+
+static spi_dev spi1 = {
+ .regs = SPI1_BASE,
+ .clk_id = RCC_SPI1,
+ .irq_num = NVIC_SPI1,
+};
+/** SPI device 1 */
+spi_dev *SPI1 = &spi1;
+
+static spi_dev spi2 = {
+ .regs = SPI2_BASE,
+ .clk_id = RCC_SPI2,
+ .irq_num = NVIC_SPI2,
+};
+/** SPI device 2 */
+spi_dev *SPI2 = &spi2;
+
+#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
+static spi_dev spi3 = {
+ .regs = SPI3_BASE,
+ .clk_id = RCC_SPI3,
+ .irq_num = NVIC_SPI3,
+};
+/** SPI device 3 */
+spi_dev *SPI3 = &spi3;
+#endif
+
+/*
+ * Routines
+ */
+
+void spi_gpio_cfg(uint8 as_master,
+ gpio_dev *nss_dev,
+ uint8 nss_bit,
+ gpio_dev *comm_dev,
+ uint8 sck_bit,
+ uint8 miso_bit,
+ uint8 mosi_bit) {
+ if (as_master) {
+ gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP);
+ gpio_set_mode(comm_dev, sck_bit, GPIO_AF_OUTPUT_PP);
+ gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING);
+ gpio_set_mode(comm_dev, mosi_bit, GPIO_AF_OUTPUT_PP);
+ } else {
+ gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING);
+ gpio_set_mode(comm_dev, sck_bit, GPIO_INPUT_FLOATING);
+ gpio_set_mode(comm_dev, miso_bit, GPIO_AF_OUTPUT_PP);
+ gpio_set_mode(comm_dev, mosi_bit, GPIO_INPUT_FLOATING);
+ }
+}
+
+void spi_foreach(void (*fn)(spi_dev*)) {
+ fn(SPI1);
+ fn(SPI2);
+#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
+ fn(SPI3);
+#endif
+}