git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6747 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2014-03-03 10:47:00 +00:00
parent 351ff9c8cc
commit 5599a0f0c3
2 changed files with 237 additions and 44 deletions

View File

@ -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

View File

@ -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. */
/*===========================================================================*/
@ -57,6 +78,22 @@
#define STM32_I2S_USE_SPI3 FALSE
#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.
*/
@ -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