aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/STM32
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-03-03 10:47:00 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-03-03 10:47:00 +0000
commit5599a0f0c36b23f3428c0d53df52d62c09284cfb (patch)
tree4a8d8163199f14f3141af90f24ae8967a7506038 /os/hal/ports/STM32
parent351ff9c8cc28b2442dcd2d894a76abd0aa747f6e (diff)
downloadChibiOS-5599a0f0c36b23f3428c0d53df52d62c09284cfb.tar.gz
ChibiOS-5599a0f0c36b23f3428c0d53df52d62c09284cfb.tar.bz2
ChibiOS-5599a0f0c36b23f3428c0d53df52d62c09284cfb.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6747 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports/STM32')
-rw-r--r--os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c231
-rw-r--r--os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h50
2 files changed, 237 insertions, 44 deletions
diff --git a/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c
index 495ab9fec..a9523060c 100644
--- a/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c
+++ b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c
@@ -30,6 +30,62 @@
/* Driver local definitions. */
/*===========================================================================*/
+#define I2S2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_RX_DMA_STREAM, \
+ STM32_SPI2_RX_DMA_CHN)
+
+#define I2S2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_TX_DMA_STREAM, \
+ STM32_SPI2_TX_DMA_CHN)
+
+#define I2S3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_RX_DMA_STREAM, \
+ STM32_SPI3_RX_DMA_CHN)
+
+#define I2S3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_TX_DMA_STREAM, \
+ STM32_SPI3_TX_DMA_CHN)
+
+/*
+ * Static I2S settings for I2S2.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */
+
+/*
+ * Static I2S settings for I2S3.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SP3_MODE) */
+
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@@ -52,6 +108,8 @@ I2SDriver I2SD3;
/* Driver local functions. */
/*===========================================================================*/
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) || \
+ STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
/**
* @brief Shared end-of-rx service routine.
*
@@ -77,7 +135,10 @@ static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) {
a macro.*/
_i2s_isr_code(i2sp);
}
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) || \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
/**
* @brief Shared end-of-tx service routine.
*
@@ -96,6 +157,7 @@ static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) {
(void)flags;
#endif
}
+#endif
/*===========================================================================*/
/* Driver interrupt handlers. */
@@ -114,12 +176,74 @@ void i2s_lld_init(void) {
#if STM32_I2S_USE_SPI2
i2sObjectInit(&I2SD2);
- I2SD2.spi = SPI2;
+ I2SD2.spi = SPI2;
+ I2SD2.cfg = STM32_I2S2_CFGR_CFG;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+ I2SD2.dmarx = STM32_DMA_STREAM(STM32_I2S_SPI2_RX_DMA_STREAM);
+ I2SD2.rxdmamode = STM32_DMA_CR_CHSEL(I2S2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD2.dmarx = NULL;
+ I2SD2.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+ I2SD2.dmatx = STM32_DMA_STREAM(STM32_I2S_SPI2_TX_DMA_STREAM);
+ I2SD2.txdmamode = STM32_DMA_CR_CHSEL(I2S2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD2.dmatx = NULL;
+ I2SD2.txdmamode = 0;
+#endif
#endif
#if STM32_I2S_USE_SPI3
i2sObjectInit(&I2SD3);
- I2SD3.spi = SPI3;
+ I2SD3.spi = SPI3;
+ I2SD3.cfg = STM32_I2S3_CFGR_CFG;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+ I2SD3.dmarx = STM32_DMA_STREAM(STM32_I2S_SPI3_RX_DMA_STREAM);
+ I2SD3.rxdmamode = STM32_DMA_CR_CHSEL(I2S3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD3.dmarx = NULL;
+ I2SD3.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+ I2SD3.dmatx = STM32_DMA_STREAM(STM32_I2S_SPI3_TX_DMA_STREAM);
+ I2SD3.txdmamode = STM32_DMA_CR_CHSEL(I2S3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD3.dmatx = NULL;
+ I2SD3.txdmamode = 0;
+#endif
#endif
}
@@ -132,55 +256,86 @@ void i2s_lld_init(void) {
*/
void i2s_lld_start(I2SDriver *i2sp) {
- osalDbgAssert(!((i2sp->config->tx_buffer != NULL) &&
- (i2sp->config->rx_buffer != NULL)),
- "full duplex not supported");
-
/* If in stopped state then enables the SPI and DMA clocks.*/
if (i2sp->state == I2S_STOP) {
+ uint32_t dmasize;
+
#if STM32_I2S_USE_SPI2
if (&I2SD2 == i2sp) {
bool b;
- if (NULL != i2sp->config->rx_buffer) {
- b = dmaStreamAllocate(i2sp->dmarx,
- STM32_I2S_SPI2_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
- (void *)i2sp);
- osalDbgAssert(!b, "stream already allocated");
- }
- if (NULL != i2sp->config->tx_buffer) {
- b = dmaStreamAllocate(i2sp->dmatx,
- STM32_I2S_SPI2_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
- (void *)i2sp);
- osalDbgAssert(!b, "stream already allocated");
- }
+
+ /* Enabling I2S unit clock.*/
rccEnableSPI2(FALSE);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+ b = dmaStreamAllocate(i2sp->dmarx,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+ b = dmaStreamAllocate(i2sp->dmatx,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
}
#endif
#if STM32_I2S_USE_SPI3
if (&I2SD3 == i2sp) {
bool b;
- if (NULL != i2sp->config->rx_buffer) {
- b = dmaStreamAllocate(i2sp->dmarx,
- STM32_I2S_SPI3_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
- (void *)i2sp);
- osalDbgAssert(!b, "stream already allocated");
- }
- if (NULL != i2sp->config->tx_buffer) {
- b = dmaStreamAllocate(i2sp->dmatx,
- STM32_I2S_SPI3_IRQ_PRIORITY,
- (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
- (void *)i2sp);
- osalDbgAssert(!b, "stream already allocated");
- }
+
+ /* Enabling I2S unit clock.*/
rccEnableSPI3(FALSE);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+ b = dmaStreamAllocate(i2sp->dmarx,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
+
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+ b = dmaStreamAllocate(i2sp->dmatx,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
+
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
}
#endif
+
+ /* DMA configuration.*/
+ if ((i2sp->config->i2scfgr & (SPI_I2SCFGR_DATLEN |
+ SPI_I2SCFGR_CHLEN)) == 0)
+ dmasize = STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ else
+ dmasize = STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
+ dmaStreamSetMode(i2sp->dmarx, i2sp->rxdmamode | dmasize);
+ dmaStreamSetMode(i2sp->dmatx, i2sp->txdmamode | dmasize);
}
- /* Configuration.*/
- i2sp->spi->CR1 = 0;
+
+ /* I2S configuration.*/
+ i2sp->spi->I2SPR = i2sp->config->i2spr;
+ i2sp->spi->I2SCFGR = i2sp->config->i2scfgr | i2sp->cfg | SPI_I2SCFGR_I2SMOD;
}
/**
@@ -197,9 +352,9 @@ void i2s_lld_stop(I2SDriver *i2sp) {
/* SPI disable.*/
i2sp->spi->CR2 = 0;
- if (NULL != i2sp->config->rx_buffer)
+ if (NULL != i2sp->dmarx)
dmaStreamRelease(i2sp->dmarx);
- if (NULL != i2sp->config->tx_buffer)
+ if (NULL != i2sp->dmatx)
dmaStreamRelease(i2sp->dmatx);
#if STM32_I2S_USE_SPI2
diff --git a/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h
index 02856dd09..ac1ff3d15 100644
--- a/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h
+++ b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h
@@ -31,6 +31,27 @@
/* Driver constants. */
/*===========================================================================*/
+/**
+ * @name Static I2S modes
+ * @{
+ */
+#define STM32_I2S_MODE_SLAVE 0
+#define STM32_I2S_MODE_MASTER 1
+#define STM32_I2S_MODE_RX 2
+#define STM32_I2S_MODE_TX 4
+#define STM32_I2S_MODE_RXTX (STM32_I2S_MODE_RX | \
+ STM32_I2S_MODE_TX)
+/** @} */
+
+/**
+ * @name Mode checks
+ * @{
+ */
+#define STM32_I2S_IS_MASTER(mode) ((mode) & STM32_I2S_MODE_MASTER)
+#define STM32_I2S_RX_ENABLED(mode) ((mode) & STM32_I2S_MODE_RX)
+#define STM32_I2S_TX_ENABLED(mode) ((mode) & STM32_I2S_MODE_TX)
+/** @} */
+
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@@ -58,6 +79,22 @@
#endif
/**
+ * @brief I2S2 mode.
+ */
+#if !defined(STM32_I2S_SPI2_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
+ * @brief I2S3 mode.
+ */
+#if !defined(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
* @brief I2S2 interrupt priority level setting.
*/
#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
@@ -109,7 +146,6 @@
#error "I2S driver activated but no SPI peripheral assigned"
#endif
-
#if STM32_I2S_USE_SPI2 && \
!CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to SPI2"
@@ -120,7 +156,6 @@
#error "Invalid IRQ priority assigned to SPI3"
#endif
-
#if STM32_I2S_USE_SPI2 && \
!STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY)
#error "Invalid DMA priority assigned to SPI2"
@@ -131,7 +166,6 @@
#error "Invalid DMA priority assigned to SPI3"
#endif
-
/* The following checks are only required when there is a DMA able to
reassign streams to different channels.*/
#if STM32_ADVANCED_DMA
@@ -251,11 +285,15 @@ struct I2SDriver {
*/
SPI_TypeDef *spi;
/**
- * @brief Receive DMA stream.
+ * @brief Calculated part of the I2SCFGR register.
+ */
+ uint16_t cfg;
+ /**
+ * @brief Receive DMA stream or @p NULL.
*/
const stm32_dma_stream_t *dmarx;
/**
- * @brief Transmit DMA stream.
+ * @brief Transmit DMA stream or @p NULL.
*/
const stm32_dma_stream_t *dmatx;
/**
@@ -281,7 +319,7 @@ extern I2SDriver I2SD2;
#endif
#if STM32_I2S_USE_I2S3 && !defined(__DOXYGEN__)
-extern I2SDriver SPI3;
+extern I2SDriver I2SD3;
#endif
#ifdef __cplusplus