aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
Diffstat (limited to 'os')
-rw-r--r--os/hal/hal.mk5
-rw-r--r--os/hal/include/hal.h1
-rw-r--r--os/hal/include/i2s.h175
-rw-r--r--os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c (renamed from os/hal/ports/STM32/LLD/i2s_lld.c)131
-rw-r--r--os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h (renamed from os/hal/ports/STM32/LLD/i2s_lld.h)179
-rw-r--r--os/hal/ports/STM32/LLD/SPIv1/spi_lld.h12
-rw-r--r--os/hal/ports/STM32/LLD/SPIv2/spi_lld.h7
-rw-r--r--os/hal/ports/STM32/STM32F4xx/platform.mk1
-rw-r--r--os/hal/src/hal.c3
-rw-r--r--os/hal/src/i2s.c159
10 files changed, 538 insertions, 135 deletions
diff --git a/os/hal/hal.mk b/os/hal/hal.mk
index 03c9ee2ad..892f1ed5d 100644
--- a/os/hal/hal.mk
+++ b/os/hal/hal.mk
@@ -1,5 +1,5 @@
-# List of all the ChibiOS/RT HAL files, there is no need to remove the files
-# from this list, you can disable parts of the kernel by editing halconf.h.
+# List of all the ChibiOS/HAL files, there is no need to remove the files
+# from this list, you can disable parts of the HAL by editing halconf.h.
HALSRC = ${CHIBIOS}/os/hal/src/hal.c \
${CHIBIOS}/os/hal/src/hal_queues.c \
${CHIBIOS}/os/hal/src/hal_mmcsd.c \
@@ -8,6 +8,7 @@ HALSRC = ${CHIBIOS}/os/hal/src/hal.c \
${CHIBIOS}/os/hal/src/ext.c \
${CHIBIOS}/os/hal/src/gpt.c \
${CHIBIOS}/os/hal/src/i2c.c \
+ ${CHIBIOS}/os/hal/src/i2s.c \
${CHIBIOS}/os/hal/src/icu.c \
${CHIBIOS}/os/hal/src/mmc_spi.c \
${CHIBIOS}/os/hal/src/pal.c \
diff --git a/os/hal/include/hal.h b/os/hal/include/hal.h
index 01ed0dd1d..a66376f3b 100644
--- a/os/hal/include/hal.h
+++ b/os/hal/include/hal.h
@@ -51,6 +51,7 @@
#include "ext.h"
#include "gpt.h"
#include "i2c.h"
+#include "i2s.h"
#include "icu.h"
//#include "mac.h"
#include "pwm.h"
diff --git a/os/hal/include/i2s.h b/os/hal/include/i2s.h
new file mode 100644
index 000000000..ae7d0173b
--- /dev/null
+++ b/os/hal/include/i2s.h
@@ -0,0 +1,175 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file i2s.h
+ * @brief I2S Driver macros and structures.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#ifndef _I2S_H_
+#define _I2S_H_
+
+#if HAL_USE_I2S || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name I2S modes
+ * @{
+ */
+#define I2S_MODE_SLAVE 0
+#define I2S_MODE_MASTER 1
+#define I2S_MODE_TX 2
+#define I2S_MODE_RX 4
+#define I2S_MODE_TXRX (I2S_MODE_TX | I2S_MODE_RX)
+#define I2S_MODE_CONTINUOUS 16
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ I2S_UNINIT = 0, /**< Not initialized. */
+ I2S_STOP = 1, /**< Stopped. */
+ I2S_READY = 2, /**< Ready. */
+ I2S_ACTIVE = 3, /**< Active. */
+ I2S_COMPLETE = 4 /**< Transmission complete. */
+} i2sstate_t;
+
+#include "i2s_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Starts a I2S data exchange.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @iclass
+ */
+#define i2sStartExchangeI(i2sp) { \
+ i2s_lld_start_exchange(i2sp); \
+ (i2sp)->state = I2S_ACTIVE; \
+}
+
+/**
+ * @brief Stops the ongoing data exchange.
+ * @details The ongoing data exchange, if any, is stopped, if the driver
+ * was not active the function does nothing.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @iclass
+ */
+#define i2sStopExchangeI(i2sp) { \
+ i2s_lld_stop_exchange(i2sp); \
+ (i2sp)->state = I2S_READY; \
+}
+
+/**
+ * @brief Common ISR code, half buffer event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] i2sp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define _i2S_isr_half_code(i2sp) { \
+ if ((i2sp)->end_cb != NULL) { \
+ (i2sp)->end_cb(i2sp, 0, (i2sp)->config->depth / 2); \
+ } \
+}
+
+/**
+ * @brief Common ISR code.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] i2sp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define _i2s_isr_code(i2sp) { \
+ if ((i2sp)->config->end_cb) { \
+ (i2sp)->state = I2S_COMPLETE; \
+ (i2sp)->config->end_cb(i2sp, \
+ (i2sp)->config->depth / 2, \
+ (i2sp)->config->depth / 2); \
+ if ((i2sp)->state == I2S_COMPLETE) \
+ (i2sp)->state = I2S_READY; \
+ } \
+ else \
+ (i2sp)->state = I2S_READY; \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2sInit(void);
+ void i2sObjectInit(I2SDriver *i2sp);
+ void i2sStart(I2SDriver *i2sp, const I2SConfig *config);
+ void i2sStop(I2SDriver *i2sp);
+ void i2sStartExchange(I2SDriver *i2sp);
+ void i2sStopExchange(I2SDriver *i2sp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2S */
+
+#endif /* _I2S_H_ */
+
+/** @} */
diff --git a/os/hal/ports/STM32/LLD/i2s_lld.c b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c
index b7eaf4b0c..9e4924501 100644
--- a/os/hal/ports/STM32/LLD/i2s_lld.c
+++ b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c
@@ -15,14 +15,13 @@
*/
/**
- * @file STM32/i2s_lld.c
+ * @file i2s_lld.c
* @brief I2S Driver subsystem low level driver source template.
*
* @addtogroup I2S
* @{
*/
-#include "ch.h"
#include "hal.h"
#if HAL_USE_I2S || defined(__DOXYGEN__)
@@ -35,6 +34,16 @@
/* Driver exported variables. */
/*===========================================================================*/
+/** @brief I2S2 driver identifier.*/
+#if STM32_I2S_USE_SPI2 || defined(__DOXYGEN__)
+I2SDriver I2SD2;
+#endif
+
+/** @brief I2S3 driver identifier.*/
+#if STM32_I2S_USE_SPI3 || defined(__DOXYGEN__)
+I2SDriver I2SD3;
+#endif
+
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
@@ -43,6 +52,51 @@
/* Driver local functions. */
/*===========================================================================*/
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2S_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2S_DMA_ERROR_HOOK(i2sp);
+ }
+#else
+ (void)flags;
+#endif
+
+ /* Stop everything.*/
+ dmaStreamDisable(i2sp->dmatx);
+ dmaStreamDisable(i2sp->dmarx);
+
+ /* Portable I2S ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _i2s_isr_code(i2sp);
+}
+
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2S_DMA_ERROR_HOOK)
+ (void)i2sp;
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2S_DMA_ERROR_HOOK(i2sp);
+ }
+#else
+ (void)flags;
+#endif
+}
+
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
@@ -58,13 +112,13 @@
*/
void i2s_lld_init(void) {
-#if STM32_I2S_USE_I2S2
- spiObjectInit(&I2SD2);
+#if STM32_I2S_USE_SPI2
+ i2sObjectInit(&I2SD2);
I2SD2.spi = SPI2;
#endif
-#if STM32_I2S_USE_I2S3
- spiObjectInit(&I2SD3);
+#if STM32_I2S_USE_SPI3
+ i2sObjectInit(&I2SD3);
I2SD3.spi = SPI3;
#endif
}
@@ -80,25 +134,35 @@ void i2s_lld_start(I2SDriver *i2sp) {
/* If in stopped state then enables the SPI and DMA clocks.*/
if (i2sp->state == I2S_STOP) {
-#if STM32_SPI_USE_SPI2
- if (&SPID2 == spip) {
- bool_t b;
- b = dmaStreamAllocate(spip->dma,
- STM32_I2S_I2S2_IRQ_PRIORITY,
+#if STM32_I2S_USE_SPI2
+ if (&I2SD2 == i2sp) {
+ bool b;
+ b = dmaStreamAllocate(i2sp->dmarx,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
(stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
- (void *)spip);
- chDbgAssert(!b, "spi_lld_start(), #1", "stream already allocated");
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(i2sp->dmatx,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
rccEnableSPI2(FALSE);
}
#endif
-#if STM32_SPI_USE_SPI3
- if (&SPID3 == spip) {
- bool_t b;
- b = dmaStreamAllocate(spip->dma,
- STM32_I2S_I2S3_IRQ_PRIORITY,
+#if STM32_I2S_USE_SPI3
+ if (&I2SD3 == i2sp) {
+ bool b;
+ b = dmaStreamAllocate(i2sp->dmarx,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
(stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
- (void *)spip);
- chDbgAssert(!b, "spi_lld_start(), #2", "stream already allocated");
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
+ b = dmaStreamAllocate(i2sp->dmatx,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(!b, "stream already allocated");
rccEnableSPI3(FALSE);
}
#endif
@@ -115,9 +179,23 @@ void i2s_lld_start(I2SDriver *i2sp) {
*/
void i2s_lld_stop(I2SDriver *i2sp) {
+ /* If in ready state then disables the SPI clock.*/
if (i2sp->state == I2S_READY) {
- /* Clock deactivation.*/
+ /* SPI disable.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = 0;
+ dmaStreamRelease(i2sp->dmarx);
+ dmaStreamRelease(i2sp->dmatx);
+
+#if STM32_I2S_USE_SPI2
+ if (&I2SD2 == i2sp)
+ rccDisableSPI2(FALSE);
+#endif
+#if STM32_I2S_USE_SPI3
+ if (&I2SD3 == i2sp)
+ rccDisableSPI3(FALSE);
+#endif
}
}
@@ -133,17 +211,6 @@ void i2s_lld_start_exchange(I2SDriver *i2sp) {
}
/**
- * @brief Starts a I2S data exchange in continuous mode.
- *
- * @param[in] i2sp pointer to the @p I2SDriver object
- *
- * @notapi
- */
-void i2s_lld_start_exchange_continuous(I2SDriver *i2sp) {
-
-}
-
-/**
* @brief Stops the ongoing data exchange.
* @details The ongoing data exchange, if any, is stopped, if the driver
* was not active the function does nothing.
diff --git a/os/hal/ports/STM32/LLD/i2s_lld.h b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h
index 3f9c640b3..a3ea2e1c4 100644
--- a/os/hal/ports/STM32/LLD/i2s_lld.h
+++ b/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.h
@@ -15,7 +15,7 @@
*/
/**
- * @file STM32/i2s_lld.h
+ * @file i2s_lld.h
* @brief I2S Driver subsystem low level driver header template.
*
* @addtogroup I2S
@@ -44,8 +44,8 @@
* @details If set to @p TRUE the support for I2S2 is included.
* @note The default is @p TRUE.
*/
-#if !defined(STM32_I2S_USE_I2S2) || defined(__DOXYGEN__)
-#define STM32_I2S_USE_I2S2 FALSE
+#if !defined(STM32_I2S_USE_SPI2) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI2 FALSE
#endif
/**
@@ -53,126 +53,120 @@
* @details If set to @p TRUE the support for I2S3 is included.
* @note The default is @p TRUE.
*/
-#if !defined(STM32_I2S_USE_I2S3) || defined(__DOXYGEN__)
-#define STM32_I2S_USE_I2S3 FALSE
+#if !defined(STM32_I2S_USE_SPI3) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI3 FALSE
#endif
/**
* @brief I2S2 interrupt priority level setting.
*/
-#if !defined(STM32_I2S_I2S2_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S2_IRQ_PRIORITY 10
+#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_IRQ_PRIORITY 10
#endif
/**
* @brief I2S3 interrupt priority level setting.
*/
-#if !defined(STM32_I2S_I2S3_IRQ_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S3_IRQ_PRIORITY 10
+#if !defined(STM32_I2S_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_IRQ_PRIORITY 10
#endif
/**
* @brief I2S2 DMA priority (0..3|lowest..highest).
*/
-#if !defined(STM32_I2S_I2S2_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S2_DMA_PRIORITY 1
+#if !defined(STM32_I2S_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_DMA_PRIORITY 1
#endif
/**
* @brief I2S3 DMA priority (0..3|lowest..highest).
*/
-#if !defined(STM32_I2S_I2S2_DMA_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S2_DMA_PRIORITY 1
+#if !defined(STM32_I2S_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_DMA_PRIORITY 1
#endif
/**
* @brief I2S DMA error hook.
*/
#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
-#define STM32_I2S_DMA_ERROR_HOOK(i2sp) chSysHalt()
+#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure")
#endif
+/** @} */
-#if STM32_ADVANCED_DMA || defined(__DOXYGEN__)
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
-/**
- * @brief DMA stream used for I2S2 RX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2S_I2S2_RX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S2_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0)
+#if STM32_I2S_USE_SPI2 && !STM32_HAS_SPI2
+#error "SPI2 not present in the selected device"
#endif
-/**
- * @brief DMA stream used for I2S2 TX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2S_I2S2_TX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#if STM32_I2S_USE_SPI3 && !STM32_HAS_SPI3
+#error "SPI3 not present in the selected device"
#endif
-/**
- * @brief DMA stream used for I2S3 RX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2S_I2S3_RX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
+#if !STM32_I2S_USE_SPI2 && !STM32_I2S_USE_SPI3
+#error "I2S driver activated but no SPI peripheral assigned"
#endif
-/**
- * @brief DMA stream used for I2S3 TX operations.
- * @note This option is only available on platforms with enhanced DMA.
- */
-#if !defined(STM32_I2S_I2S3_TX_DMA_STREAM) || defined(__DOXYGEN__)
-#define STM32_I2S_I2S3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+
+#if STM32_I2S_USE_SPI2 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
#endif
-#else /* !STM32_ADVANCED_DMA */
+#if STM32_I2S_USE_SPI3 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_I2S_SPI3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI3"
+#endif
-/* Fixed streams for platforms using the old DMA peripheral, the values are
- valid for both STM32F1xx and STM32L1xx.*/
-#define STM32_I2S_I2S2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
-#define STM32_I2S_I2S2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
-#define STM32_I2S_I2S3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
-#define STM32_I2S_I2S3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
-#endif /* !STM32_ADVANCED_DMA */
-/** @} */
-
-/*===========================================================================*/
-/* Derived constants and error checks. */
-/*===========================================================================*/
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI2"
+#endif
-#if STM32_I2S_USE_I2S2 && !STM32_HAS_SPI2
-#error "SPI2 not present in the selected device"
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI3"
#endif
-#if STM32_I2S_USE_I2S3 && !STM32_HAS_SPI3
-#error "SPI3 not present in the selected device"
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_I2S_USE_SPI2 && (!defined(STM32_I2S_SPI2_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI2_TX_DMA_STREAM))
+#error "SPI2 DMA streams not defined"
#endif
-#if !STM32_I2S_USE_I2S2 && !STM32_I2S_USE_I2S3
-#error "I2S driver activated but no I2S peripheral assigned"
+#if STM32_I2S_USE_SPI3 && (!defined(STM32_I2S_SPI3_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI3_TX_DMA_STREAM))
+#error "SPI3 DMA streams not defined"
#endif
-#if STM32_I2S_USE_I2S2 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2S2 RX"
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 RX"
#endif
-#if STM32_I2S_USE_I2S2 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2S2 TX"
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 TX"
#endif
-#if STM32_I2S_USE_I2S3 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK)
-#error "invalid DMA stream associated to I2S3 RX"
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 RX"
#endif
-#if STM32_I2S_USE_I2S3 && \
- !STM32_DMA_IS_VALID_ID(STM32_I2S_I2S3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK)
-#error "invalid DMA stream associated to I2S3 TX"
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 TX"
#endif
+#endif /* STM32_ADVANCED_DMA */
#if !defined(STM32_DMA_REQUIRED)
#define STM32_DMA_REQUIRED
@@ -196,10 +190,10 @@ typedef struct I2SDriver I2SDriver;
* @brief I2S notification callback type.
*
* @param[in] i2sp pointer to the @p I2SDriver object
- * @param[in] buffer pointer to the buffer
- * @param[in] n number of sample positions starting from @p buffer
+ * @param[in] offset offset in buffers of the data to read/write
+ * @param[in] n number of samples to read/write
*/
-typedef void (*i2scallback_t)(I2SDriver *i2sp, void *buffer, size_t n);
+typedef void (*i2scallback_t)(I2SDriver *i2sp, size_t offset, size_t n);
/**
* @brief Driver configuration structure.
@@ -212,28 +206,22 @@ typedef struct {
i2smode_t mode;
/**
* @brief Transmission buffer pointer.
+ * @note Can be @p NULL if TX is not required.
*/
const void *tx_buffer;
/**
- * @brief Transmission buffer size in number of samples.
- */
- size_t tx_size;
- /**
- * @brief Callback function associated to the transmission or @p NULL.
- */
- i2scallback_t tx_cb;
- /**
* @brief Receive buffer pointer.
+ * @note Can be @p NULL if RX is not required.
*/
void *rx_buffer;
/**
- * @brief Receive buffer size in number of samples.
+ * @brief TX and RX buffers size in number of samples.
*/
- size_t rx_size;
+ size_t depth;
/**
- * @brief Callback function associated to the reception or @p NULL.
+ * @brief Callback function called during streaming.
*/
- i2scallback_t rx_cb;;
+ i2scallback_t end_cb;
/* End of the mandatory fields.*/
/**
* @brief Configuration of the I2SCFGR register.
@@ -272,13 +260,21 @@ struct I2SDriver {
*/
SPI_TypeDef *spi;
/**
- * @brief DMA stream.
+ * @brief Receive DMA stream.
+ */
+ const stm32_dma_stream_t *dmarx;
+ /**
+ * @brief Transmit DMA stream.
+ */
+ const stm32_dma_stream_t *dmatx;
+ /**
+ * @brief RX DMA mode bit mask.
*/
- const stm32_dma_stream_t *dma;
+ uint32_t rxdmamode;
/**
- * @brief DMA mode bit mask.
+ * @brief TX DMA mode bit mask.
*/
- uint32_t dmamode;
+ uint32_t txdmamode;
};
/*===========================================================================*/
@@ -289,12 +285,12 @@ struct I2SDriver {
/* External declarations. */
/*===========================================================================*/
-#if STM32_I2S_USE_I2S2 && !defined(__DOXYGEN__)
+#if STM32_I2S_USE_SPI2 && !defined(__DOXYGEN__)
extern I2SDriver I2SD2;
#endif
#if STM32_I2S_USE_I2S3 && !defined(__DOXYGEN__)
-extern I2SDriver I2SD3;
+extern I2SDriver SPI3;
#endif
#ifdef __cplusplus
@@ -304,7 +300,6 @@ extern "C" {
void i2s_lld_start(I2SDriver *i2sp);
void i2s_lld_stop(I2SDriver *i2sp);
void i2s_lld_start_exchange(I2SDriver *i2sp);
- void i2s_lld_start_exchange_continuous(I2SDriver *i2sp);
void i2s_lld_stop_exchange(I2SDriver *i2sp);
#ifdef __cplusplus
}
diff --git a/os/hal/ports/STM32/LLD/SPIv1/spi_lld.h b/os/hal/ports/STM32/LLD/SPIv1/spi_lld.h
index fe31daeff..7700c34fe 100644
--- a/os/hal/ports/STM32/LLD/SPIv1/spi_lld.h
+++ b/os/hal/ports/STM32/LLD/SPIv1/spi_lld.h
@@ -42,7 +42,7 @@
/**
* @brief SPI1 driver enable switch.
* @details If set to @p TRUE the support for SPI1 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI1 FALSE
@@ -51,7 +51,7 @@
/**
* @brief SPI2 driver enable switch.
* @details If set to @p TRUE the support for SPI2 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI2 FALSE
@@ -60,7 +60,7 @@
/**
* @brief SPI3 driver enable switch.
* @details If set to @p TRUE the support for SPI3 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI3 FALSE
@@ -69,7 +69,7 @@
/**
* @brief SPI4 driver enable switch.
* @details If set to @p TRUE the support for SPI4 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI4 FALSE
@@ -78,7 +78,7 @@
/**
* @brief SPI5 driver enable switch.
* @details If set to @p TRUE the support for SPI5 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI5 FALSE
@@ -87,7 +87,7 @@
/**
* @brief SPI6 driver enable switch.
* @details If set to @p TRUE the support for SPI6 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI6 FALSE
diff --git a/os/hal/ports/STM32/LLD/SPIv2/spi_lld.h b/os/hal/ports/STM32/LLD/SPIv2/spi_lld.h
index 72ed48c94..0be4f5c48 100644
--- a/os/hal/ports/STM32/LLD/SPIv2/spi_lld.h
+++ b/os/hal/ports/STM32/LLD/SPIv2/spi_lld.h
@@ -42,7 +42,7 @@
/**
* @brief SPI1 driver enable switch.
* @details If set to @p TRUE the support for SPI1 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI1 FALSE
@@ -51,7 +51,7 @@
/**
* @brief SPI2 driver enable switch.
* @details If set to @p TRUE the support for SPI2 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI2 FALSE
@@ -60,7 +60,7 @@
/**
* @brief SPI3 driver enable switch.
* @details If set to @p TRUE the support for SPI3 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p FALSE.
*/
#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__)
#define STM32_SPI_USE_SPI3 FALSE
@@ -123,6 +123,7 @@
#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
#endif
+/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
diff --git a/os/hal/ports/STM32/STM32F4xx/platform.mk b/os/hal/ports/STM32/STM32F4xx/platform.mk
index cfbe44433..0f793f18f 100644
--- a/os/hal/ports/STM32/STM32F4xx/platform.mk
+++ b/os/hal/ports/STM32/STM32F4xx/platform.mk
@@ -12,6 +12,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \
${CHIBIOS}/os/hal/ports/STM32/LLD/I2Cv1/i2c_lld.c \
${CHIBIOS}/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c \
${CHIBIOS}/os/hal/ports/STM32/LLD/RTCv2/rtc_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/LLD/SPIv1/i2s_lld.c \
${CHIBIOS}/os/hal/ports/STM32/LLD/SPIv1/spi_lld.c \
${CHIBIOS}/os/hal/ports/STM32/LLD/TIMv1/gpt_lld.c \
${CHIBIOS}/os/hal/ports/STM32/LLD/TIMv1/icu_lld.c \
diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c
index 7b6dc4640..aa3eca165 100644
--- a/os/hal/src/hal.c
+++ b/os/hal/src/hal.c
@@ -83,6 +83,9 @@ void halInit(void) {
#if HAL_USE_I2C || defined(__DOXYGEN__)
i2cInit();
#endif
+#if HAL_USE_I2S || defined(__DOXYGEN__)
+ i2sInit();
+#endif
#if HAL_USE_ICU || defined(__DOXYGEN__)
icuInit();
#endif
diff --git a/os/hal/src/i2s.c b/os/hal/src/i2s.c
new file mode 100644
index 000000000..e2b51ec98
--- /dev/null
+++ b/os/hal/src/i2s.c
@@ -0,0 +1,159 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file i2s.c
+ * @brief I2S Driver code.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2S || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief I2S Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void i2sInit(void) {
+
+ i2s_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p I2SDriver structure.
+ *
+ * @param[out] i2sp pointer to the @p I2SDriver object
+ *
+ * @init
+ */
+void i2sObjectInit(I2SDriver *i2sp) {
+
+ i2sp->state = I2S_STOP;
+ i2sp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] config pointer to the @p I2SConfig object
+ *
+ * @api
+ */
+void i2sStart(I2SDriver *i2sp, const I2SConfig *config) {
+
+ osalDbgCheck((i2sp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY),
+ "invalid state");
+ i2sp->config = config;
+ i2s_lld_start(i2sp);
+ i2sp->state = I2S_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @api
+ */
+void i2sStop(I2SDriver *i2sp) {
+
+ osalDbgCheck(i2sp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY),
+ "invalid state");
+ i2s_lld_stop(i2sp);
+ i2sp->state = I2S_STOP;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts a I2S data exchange.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @api
+ */
+void i2sStartExchange(I2SDriver *i2sp) {
+
+ osalDbgCheck(i2sp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(i2sp->state == I2S_READY, "not ready");
+ i2sStartExchangeI(i2sp);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops the ongoing data exchange.
+ * @details The ongoing data exchange, if any, is stopped, if the driver
+ * was not active the function does nothing.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @api
+ */
+void i2sStopExchange(I2SDriver *i2sp) {
+
+ osalDbgCheck((i2sp != NULL));
+
+ osalSysLock();
+ osalDbgAssert((i2sp->state == I2S_READY) ||
+ (i2sp->state == I2S_ACTIVE) ||
+ (i2sp->state == I2S_COMPLETE),
+ "invalid state");
+ i2sStopExchangeI(i2sp);
+ osalSysUnlock();
+}
+
+#endif /* HAL_USE_I2S */
+
+/** @} */