aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-05-24 18:31:34 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-05-24 18:31:34 +0000
commit7a6a1679a413987ffa47f2f9892e241f3448f5f0 (patch)
tree88c38d7e249eeedc7b51979486262a0c7619bc0e /os/hal
parent293eddc33f8957f1bb896ef074bb56bf2ec2f895 (diff)
downloadChibiOS-7a6a1679a413987ffa47f2f9892e241f3448f5f0.tar.gz
ChibiOS-7a6a1679a413987ffa47f2f9892e241f3448f5f0.tar.bz2
ChibiOS-7a6a1679a413987ffa47f2f9892e241f3448f5f0.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4232 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/platforms/STM32/serial_lld.c129
-rw-r--r--os/hal/platforms/STM32/serial_lld.h30
-rw-r--r--os/hal/platforms/STM32/spi_lld.c11
-rw-r--r--os/hal/platforms/STM32/spi_lld.h39
-rw-r--r--os/hal/platforms/STM32/stm32.h26
-rw-r--r--os/hal/platforms/STM32F0xx/hal_lld.h22
-rw-r--r--os/hal/platforms/STM32F0xx/platform.mk11
-rw-r--r--os/hal/platforms/STM32F0xx/serial_lld.c322
-rw-r--r--os/hal/platforms/STM32F0xx/serial_lld.h182
-rw-r--r--os/hal/platforms/STM32F0xx/stm32_dma.c296
-rw-r--r--os/hal/platforms/STM32F0xx/stm32_dma.h395
-rw-r--r--os/hal/platforms/STM32F1xx/stm32_dma.h28
-rw-r--r--os/hal/platforms/STM32F2xx/stm32_dma.h10
-rw-r--r--os/hal/platforms/STM32F4xx/stm32_dma.h10
-rw-r--r--os/hal/platforms/STM32L1xx/stm32_dma.h14
15 files changed, 985 insertions, 540 deletions
diff --git a/os/hal/platforms/STM32/serial_lld.c b/os/hal/platforms/STM32/serial_lld.c
index a93d36523..fdb99cbc8 100644
--- a/os/hal/platforms/STM32/serial_lld.c
+++ b/os/hal/platforms/STM32/serial_lld.c
@@ -82,6 +82,129 @@ static const SerialConfig default_config =
/* Driver local functions. */
/*===========================================================================*/
+/* Local functions have different implementations depending on the USART type,
+ STM32F0xx devices and newer have and enhanced peripheral with slightly
+ different register interface.*/
+
+#if defined(STM32F0XX)
+
+/**
+ * @brief USART initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration
+ */
+static void usart_init(SerialDriver *sdp, const SerialConfig *config) {
+ USART_TypeDef *u = sdp->usart;
+
+ /*
+ * Baud rate setting.
+ */
+ if (sdp->usart == USART1)
+ u->BRR = STM32_USART1CLK / config->sc_speed;
+ else
+ u->BRR = STM32_PCLK / config->sc_speed;
+
+ /*
+ * Note that some bits are enforced.
+ */
+ u->CR1 = config->sc_cr1 | USART_CR1_UE | USART_CR1_PEIE |
+ USART_CR1_RXNEIE | USART_CR1_TE |
+ USART_CR1_RE;
+ u->CR2 = config->sc_cr2 | USART_CR2_LBDIE;
+ u->CR3 = config->sc_cr3 | USART_CR3_EIE;
+ u->ICR = 0xFFFFFFFF;
+}
+
+/**
+ * @brief USART de-initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] u pointer to an USART I/O block
+ */
+static void usart_deinit(USART_TypeDef *u) {
+
+ u->CR1 = 0;
+ u->CR2 = 0;
+ u->CR3 = 0;
+}
+
+/**
+ * @brief Error handling routine.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] isr USART ISR register value
+ */
+static void set_error(SerialDriver *sdp, uint16_t isr) {
+ chnflags_t sts = 0;
+
+ if (isr & USART_ISR_ORE)
+ sts |= SD_OVERRUN_ERROR;
+ if (isr & USART_ISR_PE)
+ sts |= SD_PARITY_ERROR;
+ if (isr & USART_ISR_FE)
+ sts |= SD_FRAMING_ERROR;
+ if (isr & USART_ISR_NE)
+ sts |= SD_NOISE_ERROR;
+ chSysLockFromIsr();
+ chnAddFlagsI(sdp, sts);
+ chSysUnlockFromIsr();
+}
+
+/**
+ * @brief Common IRQ handler.
+ *
+ * @param[in] sdp communication channel associated to the USART
+ */
+static void serve_interrupt(SerialDriver *sdp) {
+ USART_TypeDef *u = sdp->usart;
+ uint16_t cr1 = u->CR1;
+ uint16_t isr;
+
+ /* Reading and clearing status.*/
+ isr = u->ISR;
+ u->ICR = isr;
+
+ /* Error condition detection.*/
+ if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE))
+ set_error(sdp, isr);
+ /* Special case, LIN break detection.*/
+ if (isr & USART_ISR_LBD) {
+ chSysLockFromIsr();
+ chnAddFlagsI(sdp, SD_BREAK_DETECTED);
+ chSysUnlockFromIsr();
+ }
+ /* Data available.*/
+ if (isr & USART_ISR_RXNE) {
+ chSysLockFromIsr();
+ sdIncomingDataI(sdp, (uint8_t)u->RDR);
+ chSysUnlockFromIsr();
+ }
+ /* Transmission buffer empty.*/
+ if ((cr1 & USART_CR1_TXEIE) && (isr & USART_ISR_TXE)) {
+ msg_t b;
+ chSysLockFromIsr();
+ b = chOQGetI(&sdp->oqueue);
+ if (b < Q_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
+ }
+ else
+ u->TDR = b;
+ chSysUnlockFromIsr();
+ }
+ /* Physical transmission end.*/
+ if (isr & USART_ISR_TC) {
+ chSysLockFromIsr();
+ chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
+ chSysUnlockFromIsr();
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
+ }
+}
+
+#else /* !defined(STM32F0XX) */
+
/**
* @brief USART initialization.
* @details This function must be invoked with interrupts disabled.
@@ -130,9 +253,6 @@ static void usart_deinit(USART_TypeDef *u) {
u->CR3 = 0;
}
-#if STM32_SERIAL_USE_USART1 || STM32_SERIAL_USE_USART2 || \
- STM32_SERIAL_USE_USART3 || STM32_SERIAL_USE_UART4 || \
- STM32_SERIAL_USE_UART5 || STM32_SERIAL_USE_USART6
/**
* @brief Error handling routine.
*
@@ -204,7 +324,8 @@ static void serve_interrupt(SerialDriver *sdp) {
u->SR &= ~USART_SR_TC;
}
}
-#endif
+
+#endif /* !defined(STM32F0XX) */
#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
static void notify1(GenericQueue *qp) {
diff --git a/os/hal/platforms/STM32/serial_lld.h b/os/hal/platforms/STM32/serial_lld.h
index 7589da600..20905e367 100644
--- a/os/hal/platforms/STM32/serial_lld.h
+++ b/os/hal/platforms/STM32/serial_lld.h
@@ -174,6 +174,36 @@
#error "SERIAL driver activated but no USART/UART peripheral assigned"
#endif
+#if STM32_SERIAL_USE_USART1 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART1_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if STM32_SERIAL_USE_USART2 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART2_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if STM32_SERIAL_USE_USART3 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART3_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if STM32_SERIAL_USE_UART4 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART4_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if STM32_SERIAL_USE_UART5 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_UART5_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if STM32_SERIAL_USE_USART6 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SERIAL_USART6_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
diff --git a/os/hal/platforms/STM32/spi_lld.c b/os/hal/platforms/STM32/spi_lld.c
index eeeb47f53..113b89fe1 100644
--- a/os/hal/platforms/STM32/spi_lld.c
+++ b/os/hal/platforms/STM32/spi_lld.c
@@ -273,13 +273,20 @@ void spi_lld_start(SPIDriver *spip) {
}
/* Configuration-specific DMA setup.*/
- if ((spip->config->cr1 & SPI_CR1_DFF) == 0) { /* 8 bits transfers. */
+#if defined(STM32F0XX)
+ if ((spip->config->cr1 & SPI_CR2_DS) <
+ (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0)) {
+#else /* !defined(STM32F0XX) */
+ if ((spip->config->cr1 & SPI_CR1_DFF) == 0) {
+#endif /* !defined(STM32F0XX) */
+ /* Frame width is 8 bits or smaller.*/
spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
}
- else { /* 16 bits transfers. */
+ else {
+ /* Frame width is larger than 8 bits.*/
spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
diff --git a/os/hal/platforms/STM32/spi_lld.h b/os/hal/platforms/STM32/spi_lld.h
index 7de182339..cb68065c0 100644
--- a/os/hal/platforms/STM32/spi_lld.h
+++ b/os/hal/platforms/STM32/spi_lld.h
@@ -180,6 +180,14 @@
#else /* !STM32_ADVANCED_DMA */
+#if defined(STM32F0XX)
+/* Fixed values for STM32F0xx devices.*/
+#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
+#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
+
+#else /* !defined(STM32F0XX) */
/* Fixed streams for platforms using the old DMA peripheral, the values are
valid for both STM32F1xx and STM32L1xx.*/
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
@@ -188,6 +196,7 @@
#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
+#endif /* !defined(STM32F0XX) */
#endif /* !STM32_ADVANCED_DMA*/
/** @} */
@@ -213,6 +222,36 @@
#endif
#if STM32_SPI_USE_SPI1 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
!STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK)
#error "invalid DMA stream associated to SPI1 RX"
#endif
diff --git a/os/hal/platforms/STM32/stm32.h b/os/hal/platforms/STM32/stm32.h
index 24929cf3a..49c1c08bb 100644
--- a/os/hal/platforms/STM32/stm32.h
+++ b/os/hal/platforms/STM32/stm32.h
@@ -24,6 +24,7 @@
* @pre One of the following macros must be defined before including
* this header, the macro selects the inclusion of the appropriate
* vendor header:
+ * - STM32F0XX for Entry Level devices.
* - STM32F10X_LD_VL for Value Line Low Density devices.
* - STM32F10X_MD_VL for Value Line Medium Density devices.
* - STM32F10X_LD for Performance Low Density devices.
@@ -43,24 +44,27 @@
#ifndef _STM32_H_
#define _STM32_H_
-#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \
- defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \
- defined(STM32F10X_MD) || defined(STM32F10X_HD) || \
- defined(STM32F10X_XL) || defined(STM32F10X_CL) || \
- defined(__DOXYGEN__)
+#if defined(STM32F0XX)
+#include "stm32f0xx.h"
+
+#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \
+ defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \
+ defined(STM32F10X_MD) || defined(STM32F10X_HD) || \
+ defined(STM32F10X_XL) || defined(STM32F10X_CL) || \
+ defined(__DOXYGEN__)
#include "stm32f10x.h"
-#endif
-#if defined(STM32F2XX) || defined(__DOXYGEN__)
+#elif defined(STM32F2XX) || defined(__DOXYGEN__)
#include "stm32f2xx.h"
-#endif
-#if defined(STM32F4XX) || defined(__DOXYGEN__)
+#elif defined(STM32F4XX) || defined(__DOXYGEN__)
#include "stm32f4xx.h"
-#endif
-#if defined(STM32L1XX_MD) || defined(__DOXYGEN__)
+#elif defined(STM32L1XX_MD) || defined(__DOXYGEN__)
#include "stm32l1xx.h"
+
+#else
+#error "STM32 device not specified"
#endif
/*===========================================================================*/
diff --git a/os/hal/platforms/STM32F0xx/hal_lld.h b/os/hal/platforms/STM32F0xx/hal_lld.h
index 1bd31c168..30a46fa79 100644
--- a/os/hal/platforms/STM32F0xx/hal_lld.h
+++ b/os/hal/platforms/STM32F0xx/hal_lld.h
@@ -38,7 +38,7 @@
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
-#include "stm32f0xx.h"
+#include "stm32.h"
/*===========================================================================*/
/* Driver constants. */
@@ -223,8 +223,20 @@
*/
/* ADC attributes.*/
#define STM32_HAS_ADC1 TRUE
+#define STM32_ADC1_DMA_DEFAULT STM32_DMA_STREAM_ID(1, 0)
+#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) | \
+ STM32_DMA_STREAM_ID_MSK(1, 1))
+#define STM32_ADC1_DMA_CHN 0x00000000
+
#define STM32_HAS_ADC2 FALSE
+#define STM32_ADC2_DMA_DEFAULT 0
+#define STM32_ADC2_DMA_MSK 0x00000000
+#define STM32_ADC2_DMA_CHN 0x00000000
+
#define STM32_HAS_ADC3 FALSE
+#define STM32_ADC3_DMA_DEFAULT 0
+#define STM32_ADC3_DMA_MSK 0x00000000
+#define STM32_ADC3_DMA_CHN 0x00000000
/* CAN attributes.*/
#define STM32_HAS_CAN1 FALSE
@@ -322,9 +334,11 @@
/* USART attributes.*/
#define STM32_HAS_USART1 TRUE
-#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) | \
+ STM32_DMA_STREAM_ID_MSK(1, 5))
#define STM32_USART1_RX_DMA_CHN 0x00000000
-#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) | \
+ STM32_DMA_STREAM_ID_MSK(1, 4))
#define STM32_USART1_TX_DMA_CHN 0x00000000
#define STM32_HAS_USART2 TRUE
@@ -939,7 +953,7 @@
/*===========================================================================*/
/* STM32 DMA and RCC helpers.*/
-/*#include "stm32_dma.h"*/
+#include "stm32_dma.h"
#include "stm32_rcc.h"
#ifdef __cplusplus
diff --git a/os/hal/platforms/STM32F0xx/platform.mk b/os/hal/platforms/STM32F0xx/platform.mk
index e34e8dd8e..9d13d064a 100644
--- a/os/hal/platforms/STM32F0xx/platform.mk
+++ b/os/hal/platforms/STM32F0xx/platform.mk
@@ -1,8 +1,11 @@
# List of all the STM32F1xx platform files.
-PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F0xx/hal_lld.c \
- ${CHIBIOS}/os/hal/platforms/STM32F0xx/serial_lld.c \
- ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c
+PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F0xx/stm32_dma.c \
+ ${CHIBIOS}/os/hal/platforms/STM32F0xx/hal_lld.c \
+ ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \
+ ${CHIBIOS}/os/hal/platforms/STM32/serial_lld.c \
+ ${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c
# Required include directories
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/STM32F0xx \
- ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2
+ ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \
+ ${CHIBIOS}/os/hal/platforms/STM32
diff --git a/os/hal/platforms/STM32F0xx/serial_lld.c b/os/hal/platforms/STM32F0xx/serial_lld.c
deleted file mode 100644
index a611279a4..000000000
--- a/os/hal/platforms/STM32F0xx/serial_lld.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
- 2011,2012 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 STM32/serial_lld.c
- * @brief STM32 low level serial driver code.
- *
- * @addtogroup SERIAL
- * @{
- */
-
-#include "ch.h"
-#include "hal.h"
-
-#if HAL_USE_SERIAL || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver exported variables. */
-/*===========================================================================*/
-
-/** @brief USART1 serial driver identifier.*/
-#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
-SerialDriver SD1;
-#endif
-
-/** @brief USART2 serial driver identifier.*/
-#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
-SerialDriver SD2;
-#endif
-
-/*===========================================================================*/
-/* Driver local variables. */
-/*===========================================================================*/
-
-/** @brief Driver default configuration.*/
-static const SerialConfig default_config =
-{
- SERIAL_DEFAULT_BITRATE,
- 0,
- USART_CR2_STOP1_BITS | USART_CR2_LINEN,
- 0
-};
-
-/*===========================================================================*/
-/* Driver local functions. */
-/*===========================================================================*/
-
-/**
- * @brief USART initialization.
- * @details This function must be invoked with interrupts disabled.
- *
- * @param[in] sdp pointer to a @p SerialDriver object
- * @param[in] config the architecture-dependent serial driver configuration
- */
-static void usart_init(SerialDriver *sdp, const SerialConfig *config) {
- USART_TypeDef *u = sdp->usart;
-
- /*
- * Baud rate setting.
- */
- if (sdp->usart == USART1)
- u->BRR = STM32_USART1CLK / config->sc_speed;
- else
- u->BRR = STM32_PCLK / config->sc_speed;
-
- /*
- * Note that some bits are enforced.
- */
- u->CR1 = config->sc_cr1 | USART_CR1_UE | USART_CR1_PEIE |
- USART_CR1_RXNEIE | USART_CR1_TE |
- USART_CR1_RE;
- u->CR2 = config->sc_cr2 | USART_CR2_LBDIE;
- u->CR3 = config->sc_cr3 | USART_CR3_EIE;
- u->ICR = 0xFFFFFFFF;
-}
-
-/**
- * @brief USART de-initialization.
- * @details This function must be invoked with interrupts disabled.
- *
- * @param[in] u pointer to an USART I/O block
- */
-static void usart_deinit(USART_TypeDef *u) {
-
- u->CR1 = 0;
- u->CR2 = 0;
- u->CR3 = 0;
-}
-
-#if STM32_SERIAL_USE_USART1 || STM32_SERIAL_USE_USART2
-/**
- * @brief Error handling routine.
- *
- * @param[in] sdp pointer to a @p SerialDriver object
- * @param[in] isr USART ISR register value
- */
-static void set_error(SerialDriver *sdp, uint16_t isr) {
- chnflags_t sts = 0;
-
- if (isr & USART_ISR_ORE)
- sts |= SD_OVERRUN_ERROR;
- if (isr & USART_ISR_PE)
- sts |= SD_PARITY_ERROR;
- if (isr & USART_ISR_FE)
- sts |= SD_FRAMING_ERROR;
- if (isr & USART_ISR_NE)
- sts |= SD_NOISE_ERROR;
- chSysLockFromIsr();
- chnAddFlagsI(sdp, sts);
- chSysUnlockFromIsr();
-}
-
-/**
- * @brief Common IRQ handler.
- *
- * @param[in] sdp communication channel associated to the USART
- */
-static void serve_interrupt(SerialDriver *sdp) {
- USART_TypeDef *u = sdp->usart;
- uint16_t cr1 = u->CR1;
- uint16_t isr;
-
- /* Reading and clearing status.*/
- isr = u->ISR;
- u->ICR = isr;
-
- /* Error condition detection.*/
- if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE))
- set_error(sdp, isr);
- /* Special case, LIN break detection.*/
- if (isr & USART_ISR_LBD) {
- chSysLockFromIsr();
- chnAddFlagsI(sdp, SD_BREAK_DETECTED);
- chSysUnlockFromIsr();
- }
- /* Data available.*/
- if (isr & USART_ISR_RXNE) {
- chSysLockFromIsr();
- sdIncomingDataI(sdp, (uint8_t)u->RDR);
- chSysUnlockFromIsr();
- }
- /* Transmission buffer empty.*/
- if ((cr1 & USART_CR1_TXEIE) && (isr & USART_ISR_TXE)) {
- msg_t b;
- chSysLockFromIsr();
- b = chOQGetI(&sdp->oqueue);
- if (b < Q_OK) {
- chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
- u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE;
- }
- else
- u->TDR = b;
- chSysUnlockFromIsr();
- }
- /* Physical transmission end.*/
- if (isr & USART_ISR_TC) {
- chSysLockFromIsr();
- chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
- chSysUnlockFromIsr();
- u->CR1 = cr1 & ~USART_CR1_TCIE;
- }
-}
-#endif
-
-#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
-static void notify1(GenericQueue *qp) {
-
- (void)qp;
- USART1->CR1 |= USART_CR1_TXEIE;
-}
-#endif
-
-#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
-static void notify2(GenericQueue *qp) {
-
- (void)qp;
- USART2->CR1 |= USART_CR1_TXEIE;
-}
-#endif
-
-/*===========================================================================*/
-/* Driver interrupt handlers. */
-/*===========================================================================*/
-
-#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
-/**
- * @brief USART1 interrupt handler.
- *
- * @isr
- */
-CH_IRQ_HANDLER(USART1_IRQHandler) {
-
- CH_IRQ_PROLOGUE();
-
- serve_interrupt(&SD1);
-
- CH_IRQ_EPILOGUE();
-}
-#endif
-
-#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
-/**
- * @brief USART2 interrupt handler.
- *
- * @isr
- */
-CH_IRQ_HANDLER(USART2_IRQHandler) {
-
- CH_IRQ_PROLOGUE();
-
- serve_interrupt(&SD2);
-
- CH_IRQ_EPILOGUE();
-}
-#endif
-
-/*===========================================================================*/
-/* Driver exported functions. */
-/*===========================================================================*/
-
-/**
- * @brief Low level serial driver initialization.
- *
- * @notapi
- */
-void sd_lld_init(void) {
-
-#if STM32_SERIAL_USE_USART1
- sdObjectInit(&SD1, NULL, notify1);
- SD1.usart = USART1;
-#endif
-
-#if STM32_SERIAL_USE_USART2
- sdObjectInit(&SD2, NULL, notify2);
- SD2.usart = USART2;
-#endif
-}
-
-/**
- * @brief Low level serial driver configuration and (re)start.
- *
- * @param[in] sdp pointer to a @p SerialDriver object
- * @param[in] config the architecture-dependent serial driver configuration.
- * If this parameter is set to @p NULL then a default
- * configuration is used.
- *
- * @notapi
- */
-void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
-
- if (config == NULL)
- config = &default_config;
-
- if (sdp->state == SD_STOP) {
-#if STM32_SERIAL_USE_USART1
- if (&SD1 == sdp) {
- rccEnableUSART1(FALSE);
- nvicEnableVector(USART1_IRQn,
- CORTEX_PRIORITY_MASK(STM32_SERIAL_USART1_PRIORITY));
- }
-#endif
-#if STM32_SERIAL_USE_USART2
- if (&SD2 == sdp) {
- rccEnableUSART2(FALSE);
- nvicEnableVector(USART2_IRQn,
- CORTEX_PRIORITY_MASK(STM32_SERIAL_USART2_PRIORITY));
- }
-#endif
- }
- usart_init(sdp, config);
-}
-
-/**
- * @brief Low level serial driver stop.
- * @details De-initializes the USART, stops the associated clock, resets the
- * interrupt vector.
- *
- * @param[in] sdp pointer to a @p SerialDriver object
- *
- * @notapi
- */
-void sd_lld_stop(SerialDriver *sdp) {
-
- if (sdp->state == SD_READY) {
- usart_deinit(sdp->usart);
-#if STM32_SERIAL_USE_USART1
- if (&SD1 == sdp) {
- rccDisableUSART1(FALSE);
- nvicDisableVector(USART1_IRQn);
- return;
- }
-#endif
-#if STM32_SERIAL_USE_USART2
- if (&SD2 == sdp) {
- rccDisableUSART2(FALSE);
- nvicDisableVector(USART2_IRQn);
- return;
- }
-#endif
- }
-}
-
-#endif /* HAL_USE_SERIAL */
-
-/** @} */
diff --git a/os/hal/platforms/STM32F0xx/serial_lld.h b/os/hal/platforms/STM32F0xx/serial_lld.h
deleted file mode 100644
index da41e66da..000000000
--- a/os/hal/platforms/STM32F0xx/serial_lld.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
- 2011,2012 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 STM32/serial_lld.h
- * @brief STM32 low level serial driver header.
- *
- * @addtogroup SERIAL
- * @{
- */
-
-#ifndef _SERIAL_LLD_H_
-#define _SERIAL_LLD_H_
-
-#if HAL_USE_SERIAL || defined(__DOXYGEN__)
-
-/*===========================================================================*/
-/* Driver constants. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver pre-compile time settings. */
-/*===========================================================================*/
-
-/**
- * @name Configuration options
- * @{
- */
-/**
- * @brief USART1 driver enable switch.
- * @details If set to @p TRUE the support for USART1 is included.
- * @note The default is @p TRUE.
- */
-#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__)
-#define STM32_SERIAL_USE_USART1 TRUE
-#endif
-
-/**
- * @brief USART2 driver enable switch.
- * @details If set to @p TRUE the support for USART2 is included.
- * @note The default is @p TRUE.
- */
-#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__)
-#define STM32_SERIAL_USE_USART2 TRUE
-#endif
-
-/**
- * @brief USART1 interrupt priority level setting.
- */
-#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_SERIAL_USART1_PRIORITY 3
-#endif
-
-/**
- * @brief USART2 interrupt priority level setting.
- */
-#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__)
-#define STM32_SERIAL_USART2_PRIORITY 3
-#endif
-/** @} */
-
-/*===========================================================================*/
-/* Derived constants and error checks. */
-/*===========================================================================*/
-
-#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1
-#error "USART1 not present in the selected device"
-#endif
-
-#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2
-#error "USART2 not present in the selected device"
-#endif
-
-#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2
-#error "SERIAL driver activated but no USART/UART peripheral assigned"
-#endif
-
-/*===========================================================================*/
-/* Driver data structures and types. */
-/*===========================================================================*/
-
-/**
- * @brief STM32 Serial Driver configuration structure.
- * @details An instance of this structure must be passed to @p sdStart()
- * in order to configure and start a serial driver operations.
- * @note This structure content is architecture dependent, each driver
- * implementation defines its own version and the custom static
- * initializers.
- */
-typedef struct {
- /**
- * @brief Bit rate.
- */
- uint32_t sc_speed;
- /**
- * @brief Initialization value for the CR1 register.
- */
- uint16_t sc_cr1;
- /**
- * @brief Initialization value for the CR2 register.
- */
- uint16_t sc_cr2;
- /**
- * @brief Initialization value for the CR3 register.
- */
- uint16_t sc_cr3;
-} SerialConfig;
-
-/**
- * @brief @p SerialDriver specific data.
- */
-#define _serial_driver_data \
- _base_asynchronous_channel_data \
- /* Driver state.*/ \
- sdstate_t state; \
- /* Input queue.*/ \
- InputQueue iqueue; \
- /* Output queue.*/ \
- OutputQueue oqueue; \
- /* Input circular buffer.*/ \
- uint8_t ib[SERIAL_BUFFERS_SIZE]; \
- /* Output circular buffer.*/ \
- uint8_t ob[SERIAL_BUFFERS_SIZE]; \
- /* End of the mandatory fields.*/ \
- /* Pointer to the USART registers block.*/ \
- USART_TypeDef *usart;
-
-/*===========================================================================*/
-/* Driver macros. */
-/*===========================================================================*/
-
-/*
- * Extra USARTs definitions here (missing from the ST header file).
- */
-#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/
-#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/
-#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/
-#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/
-
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
-
-#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__)
-extern SerialDriver SD1;
-#endif
-#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__)
-extern SerialDriver SD2;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
- void sd_lld_init(void);
- void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
- void sd_lld_stop(SerialDriver *sdp);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HAL_USE_SERIAL */
-
-#endif /* _SERIAL_LLD_H_ */
-
-/** @} */
diff --git a/os/hal/platforms/STM32F0xx/stm32_dma.c b/os/hal/platforms/STM32F0xx/stm32_dma.c
new file mode 100644
index 000000000..f5191f954
--- /dev/null
+++ b/os/hal/platforms/STM32F0xx/stm32_dma.c
@@ -0,0 +1,296 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012 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 STM32F0xx/stm32_dma.c
+ * @brief DMA helper driver code.
+ *
+ * @addtogroup STM32F0xx_DMA
+ * @details DMA sharing helper driver. In the STM32 the DMA streams are a
+ * shared resource, this driver allows to allocate and free DMA
+ * streams at runtime in order to allow all the other device
+ * drivers to coordinate the access to the resource.
+ * @note The DMA ISR handlers are all declared into this module because
+ * sharing, the various device drivers can associate a callback to
+ * ISRs when allocating streams.
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring DMA services
+ has been enabled.*/
+#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Mask of the DMA1 streams in @p dma_streams_mask.
+ */
+#define STM32_DMA1_STREAMS_MASK 0x0000007F
+
+/**
+ * @brief Mask of the DMA2 streams in @p dma_streams_mask.
+ */
+#define STM32_DMA2_STREAMS_MASK 0x00000F80
+
+/**
+ * @brief Post-reset value of the stream CCR register.
+ */
+#define STM32_DMA_CCR_RESET_VALUE 0x00000000
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA streams descriptors.
+ * @details This table keeps the association between an unique stream
+ * identifier and the involved physical registers.
+ * @note Don't use this array directly, use the appropriate wrapper macros
+ * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc.
+ */
+const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
+ {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn},
+ {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_3_IRQn},
+ {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel2_3_IRQn},
+ {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_5_IRQn},
+ {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel4_5_IRQn}
+};
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA ISR redirector type.
+ */
+typedef struct {
+ stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */
+ void *dma_param; /**< @brief DMA callback parameter. */
+} dma_isr_redir_t;
+
+/**
+ * @brief Mask of the allocated streams.
+ */
+static uint32_t dma_streams_mask;
+
+/**
+ * @brief DMA IRQ redirectors.
+ */
+static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS];
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA1 stream 1 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 0;
+ if (dma_isr_redir[0].dma_func)
+ dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 streams 2 and 3 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch2_3_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ /* Check on channel 2.*/
+ flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK;
+ if (flags & STM32_DMA_ISR_MASK) {
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 4;
+ if (dma_isr_redir[1].dma_func)
+ dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags);
+ }
+
+ /* Check on channel 3.*/
+ flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK;
+ if (flags & STM32_DMA_ISR_MASK) {
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 8;
+ if (dma_isr_redir[2].dma_func)
+ dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags);
+ }
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 streams 4 and 5 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch4_5_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ /* Check on channel 4.*/
+ flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK;
+ if (flags & STM32_DMA_ISR_MASK) {
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 12;
+ if (dma_isr_redir[3].dma_func)
+ dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags);
+ }
+
+ /* Check on channel 5.*/
+ flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK;
+ if (flags & STM32_DMA_ISR_MASK) {
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 16;
+ if (dma_isr_redir[4].dma_func)
+ dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags);
+ }
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA helper initialization.
+ *
+ * @init
+ */
+void dmaInit(void) {
+ int i;
+
+ dma_streams_mask = 0;
+ for (i = 0; i < STM32_DMA_STREAMS; i++) {
+ _stm32_dma_streams[i].channel->CCR = 0;
+ dma_isr_redir[i].dma_func = NULL;
+ }
+ DMA1->IFCR = 0xFFFFFFFF;
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ * @pre The stream must not be already in use or an error is returned.
+ * @post The stream is allocated and the default ISR handler redirected
+ * to the specified function.
+ * @post The stream ISR vector is enabled and its priority configured.
+ * @post The stream must be freed using @p dmaStreamRelease() before it can
+ * be reused with another peripheral.
+ * @post The stream is in its post-reset state.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] priority IRQ priority mask for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return The operation status.
+ * @retval FALSE no error, stream taken.
+ * @retval TRUE error, stream already taken.
+ *
+ * @special
+ */
+bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param) {
+
+ chDbgCheck(dmastp != NULL, "dmaAllocate");
+
+ /* Checks if the stream is already taken.*/
+ if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0)
+ return TRUE;
+
+ /* Marks the stream as allocated.*/
+ dma_isr_redir[dmastp->selfindex].dma_func = func;
+ dma_isr_redir[dmastp->selfindex].dma_param = param;
+ dma_streams_mask |= (1 << dmastp->selfindex);
+
+ /* Enabling DMA clocks required by the current streams set.*/
+ if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0)
+ rccEnableDMA1(FALSE);
+
+ /* Putting the stream in a safe state.*/
+ dmaStreamDisable(dmastp);
+ dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE;
+
+ /* Enables the associated IRQ vector if a callback is defined.*/
+ if (func != NULL)
+ nvicEnableVector(dmastp->vector, CORTEX_PRIORITY_MASK(priority));
+
+ return FALSE;
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post The stream is again available.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+void dmaStreamRelease(const stm32_dma_stream_t *dmastp) {
+
+ chDbgCheck(dmastp != NULL, "dmaRelease");
+
+ /* Check if the streams is not taken.*/
+ chDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0,
+ "dmaRelease(), #1", "not allocated");
+
+ /* Disables the associated IRQ vector.*/
+ nvicDisableVector(dmastp->vector);
+
+ /* Marks the stream as not allocated.*/
+ dma_streams_mask &= ~(1 << dmastp->selfindex);
+
+ /* Shutting down clocks that are no more required, if any.*/
+ if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0)
+ rccDisableDMA1(FALSE);
+}
+
+#endif /* STM32_DMA_REQUIRED */
+
+/** @} */
diff --git a/os/hal/platforms/STM32F0xx/stm32_dma.h b/os/hal/platforms/STM32F0xx/stm32_dma.h
new file mode 100644
index 000000000..1677bc285
--- /dev/null
+++ b/os/hal/platforms/STM32F0xx/stm32_dma.h
@@ -0,0 +1,395 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012 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 STM32F0xx/stm32_dma.h
+ * @brief DMA helper driver header.
+ * @note This file requires definitions from the ST header file stm32l1xx.h.
+ * @note This driver uses the new naming convention used for the STM32F2xx
+ * so the "DMA channels" are referred as "DMA streams".
+ *
+ * @addtogroup STM32F0xx_DMA
+ * @{
+ */
+
+#ifndef _STM32_DMA_H_
+#define _STM32_DMA_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Total number of DMA streams.
+ * @note This is the total number of streams among all the DMA units.
+ */
+#define STM32_DMA_STREAMS 5
+
+/**
+ * @brief Mask of the ISR bits passed to the DMA callback functions.
+ */
+#define STM32_DMA_ISR_MASK 0x0F
+
+/**
+ * @brief Returns the channel associated to the specified stream.
+ *
+ * @param[in] n the stream number (0...STM32_DMA_STREAMS-1)
+ * @param[in] c a stream/channel association word, one channel per
+ * nibble, not associated channels must be set to 0xF
+ * @return Always zero, in this platform there is no dynamic
+ * association between streams and channels.
+ */
+#define STM32_DMA_GETCHANNEL(n, c) 0
+
+/**
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval FALSE invalid DMA priority.
+ * @retval TRUE correct DMA priority.
+ */
+#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3))
+
+/**
+ * @brief Returns an unique numeric identifier for a DMA stream.
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return An unique numeric stream identifier.
+ */
+#define STM32_DMA_STREAM_ID(dma, stream) ((stream) - 1)
+
+/**
+ * @brief Returns a DMA stream identifier mask.
+ *
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return A DMA stream identifier mask.
+ */
+#define STM32_DMA_STREAM_ID_MSK(dma, stream) \
+ (1 << STM32_DMA_STREAM_ID(dma, stream))
+
+/**
+ * @brief Checks if a DMA stream unique identifier belongs to a mask.
+ * @param[in] id the stream numeric identifier
+ * @param[in] mask the stream numeric identifiers mask
+ *
+ * @retval The check result.
+ * @retval FALSE id does not belong to the mask.
+ * @retval TRUE id belongs to the mask.
+ */
+#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask)))
+
+/**
+ * @name DMA streams identifiers
+ * @{
+ */
+/**
+ * @brief Returns a pointer to a stm32_dma_stream_t structure.
+ *
+ * @param[in] id the stream numeric identifier
+ * @return A pointer to the stm32_dma_stream_t constant structure
+ * associated to the DMA stream.
+ */
+#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id])
+
+#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0)
+#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1)
+#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2)
+#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3)
+#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4)
+/** @} */
+
+/**
+ * @name CR register constants common to all DMA types
+ * @{
+ */
+#define STM32_DMA_CR_EN DMA_CCR_EN
+#define STM32_DMA_CR_TEIE DMA_CCR_TEIE
+#define STM32_DMA_CR_HTIE DMA_CCR_HTIE
+#define STM32_DMA_CR_TCIE DMA_CCR_TCIE
+#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM)
+#define STM32_DMA_CR_DIR_P2M 0
+#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR
+#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM
+#define STM32_DMA_CR_CIRC DMA_CCR_CIRC
+#define STM32_DMA_CR_PINC DMA_CCR_PINC
+#define STM32_DMA_CR_MINC DMA_CCR_MINC
+#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE
+#define STM32_DMA_CR_PSIZE_BYTE 0
+#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0
+#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1
+#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE
+#define STM32_DMA_CR_MSIZE_BYTE 0
+#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0
+#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1
+#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_MSIZE_MASK | \
+ STM32_DMA_CR_MSIZE_MASK)
+#define STM32_DMA_CR_PL_MASK DMA_CCR_PL
+#define STM32_DMA_CR_PL(n) ((n) << 12)
+/** @} */
+
+/**
+ * @name CR register constants only found in enhanced DMA
+ * @{
+ */
+#define STM32_DMA_CR_DMEIE 0 /**< @brief Ignored by normal DMA. */
+#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */
+#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */
+/** @} */
+
+/**
+ * @name Status flags passed to the ISR callbacks
+ * @{
+ */
+#define STM32_DMA_ISR_FEIF 0
+#define STM32_DMA_ISR_DMEIF 0
+#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1
+#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1
+#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA stream descriptor structure.
+ */
+typedef struct {
+ DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */
+ volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */
+ uint8_t ishift; /**< @brief Bits offset in xIFCR
+ register. */
+ uint8_t selfindex; /**< @brief Index to self in array. */
+ uint8_t vector; /**< @brief Associated IRQ vector. */
+} stm32_dma_stream_t;
+
+/**
+ * @brief STM32 DMA ISR function type.
+ *
+ * @param[in] p parameter for the registered function
+ * @param[in] flags pre-shifted content of the ISR register, the bits
+ * are aligned to bit zero
+ */
+typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Associates a peripheral data register to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the CPAR register
+ *
+ * @special
+ */
+#define dmaStreamSetPeripheral(dmastp, addr) { \
+ (dmastp)->channel->CPAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates a memory destination to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the CMAR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory0(dmastp, addr) { \
+ (dmastp)->channel->CMAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Sets the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] size value to be written in the CNDTR register
+ *
+ * @special
+ */
+#define dmaStreamSetTransactionSize(dmastp, size) { \
+ (dmastp)->channel->CNDTR = (uint32_t)(size); \
+}
+
+/**
+ * @brief Returns the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @return The number of transfers to be performed.
+ *
+ * @special
+ */
+#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR))
+
+/**
+ * @brief Programs the stream mode settings.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register
+ *
+ * @special
+ */
+#define dmaStreamSetMode(dmastp, mode) { \
+ (dmastp)->channel->CCR = (uint32_t)(mode); \
+}
+
+/**
+ * @brief DMA stream enable.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamEnable(dmastp) { \
+ (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \
+}
+
+/**
+ * @brief DMA stream disable.
+ * @details The function disables the specified stream and then clears any
+ * pending interrupt.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamDisable(dmastp) { \
+ (dmastp)->channel->CCR &= ~STM32_DMA_CR_EN; \
+ dmaStreamClearInterrupt(dmastp); \
+}
+
+/**
+ * @brief DMA stream interrupt sources clear.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamClearInterrupt(dmastp) { \
+ *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \
+}
+
+/**
+ * @brief Starts a memory to memory operation using the specified stream.
+ * @note The default transfer data mode is "byte to byte" but it can be
+ * changed by specifying extra options in the @p mode parameter.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register, this value
+ * is implicitly ORed with:
+ * - @p STM32_DMA_CR_MINC
+ * - @p STM32_DMA_CR_PINC
+ * - @p STM32_DMA_CR_DIR_M2M
+ * - @p STM32_DMA_CR_EN
+ * .
+ * @param[in] src source address
+ * @param[in] dst destination address
+ * @param[in] n number of data units to copy
+ */
+#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \
+ dmaStreamSetPeripheral(dmastp, src); \
+ dmaStreamSetMemory0(dmastp, dst); \
+ dmaStreamSetTransactionSize(dmastp, n); \
+ dmaStreamSetMode(dmastp, (mode) | \
+ STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \
+ STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \
+}
+
+/**
+ * @brief Polled wait for DMA transfer end.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ */
+#define dmaWaitCompletion(dmastp) { \
+ while ((dmastp)->channel->CNDTR > 0) \
+ ; \
+ dmaStreamDisable(dmastp); \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dmaInit(void);
+ bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param);
+ void dmaStreamRelease(const stm32_dma_stream_t *dmastp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STM32_DMA_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/STM32F1xx/stm32_dma.h b/os/hal/platforms/STM32F1xx/stm32_dma.h
index a4cae4ea6..aa612d592 100644
--- a/os/hal/platforms/STM32F1xx/stm32_dma.h
+++ b/os/hal/platforms/STM32F1xx/stm32_dma.h
@@ -63,6 +63,25 @@
#define STM32_DMA_GETCHANNEL(n, c) 0
/**
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval FALSE invalid DMA priority.
+ * @retval TRUE correct DMA priority.
+ */
+#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3))
+
+/**
+ * @brief Returns an unique numeric identifier for a DMA stream.
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return An unique numeric stream identifier.
+ */
+#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 7) + ((stream) - 1))
+
+/**
* @brief Returns a DMA stream identifier mask.
*
*
@@ -89,15 +108,6 @@
* @{
*/
/**
- * @brief Returns an unique numeric identifier for a DMA stream.
- *
- * @param[in] dma the DMA unit number
- * @param[in] stream the stream number
- * @return An unique numeric stream identifier.
- */
-#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 7) + ((stream) - 1))
-
-/**
* @brief Returns a pointer to a stm32_dma_stream_t structure.
*
* @param[in] id the stream numeric identifier
diff --git a/os/hal/platforms/STM32F2xx/stm32_dma.h b/os/hal/platforms/STM32F2xx/stm32_dma.h
index 53097c297..d9434acd5 100644
--- a/os/hal/platforms/STM32F2xx/stm32_dma.h
+++ b/os/hal/platforms/STM32F2xx/stm32_dma.h
@@ -57,6 +57,16 @@
#define STM32_DMA_GETCHANNEL(id, c) (((c) >> (((id) & 7) * 4)) & 7)
/**
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval FALSE invalid DMA priority.
+ * @retval TRUE correct DMA priority.
+ */
+#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3))
+
+/**
* @brief Returns an unique numeric identifier for a DMA stream.
*
* @param[in] dma the DMA unit number
diff --git a/os/hal/platforms/STM32F4xx/stm32_dma.h b/os/hal/platforms/STM32F4xx/stm32_dma.h
index 473ce9613..af466b01d 100644
--- a/os/hal/platforms/STM32F4xx/stm32_dma.h
+++ b/os/hal/platforms/STM32F4xx/stm32_dma.h
@@ -57,6 +57,16 @@
#define STM32_DMA_GETCHANNEL(id, c) (((c) >> (((id) & 7) * 4)) & 7)
/**
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval FALSE invalid DMA priority.
+ * @retval TRUE correct DMA priority.
+ */
+#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3))
+
+/**
* @brief Returns an unique numeric identifier for a DMA stream.
*
* @param[in] dma the DMA unit number
diff --git a/os/hal/platforms/STM32L1xx/stm32_dma.h b/os/hal/platforms/STM32L1xx/stm32_dma.h
index bf3f3f3ca..71af4a339 100644
--- a/os/hal/platforms/STM32L1xx/stm32_dma.h
+++ b/os/hal/platforms/STM32L1xx/stm32_dma.h
@@ -59,9 +59,15 @@
#define STM32_DMA_GETCHANNEL(n, c) 0
/**
- * @name DMA streams identifiers
- * @{
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval FALSE invalid DMA priority.
+ * @retval TRUE correct DMA priority.
*/
+#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0) && ((prio) <= 3))
+
/**
* @brief Returns an unique numeric identifier for a DMA stream.
*
@@ -94,6 +100,10 @@
#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask)))
/**
+ * @name DMA streams identifiers
+ * @{
+ */
+/**
* @brief Returns a pointer to a stm32_dma_stream_t structure.
*
* @param[in] id the stream numeric identifier