aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/STM32/STM32F4xx
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-01-24 14:27:22 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-01-24 14:27:22 +0000
commit2c1a02debfb33819d3cf604f52a97f0e26247eaa (patch)
tree46a0c64ece0482853bbd1f86f3432b88730ba507 /os/hal/ports/STM32/STM32F4xx
parent156a9e9fa71badb88476ac2bbc1219587ea8e7bb (diff)
downloadChibiOS-2c1a02debfb33819d3cf604f52a97f0e26247eaa.tar.gz
ChibiOS-2c1a02debfb33819d3cf604f52a97f0e26247eaa.tar.bz2
ChibiOS-2c1a02debfb33819d3cf604f52a97f0e26247eaa.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6644 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports/STM32/STM32F4xx')
-rw-r--r--os/hal/ports/STM32/STM32F4xx/adc_lld.c418
-rw-r--r--os/hal/ports/STM32/STM32F4xx/adc_lld.h563
-rw-r--r--os/hal/ports/STM32/STM32F4xx/ext_lld_isr.c338
-rw-r--r--os/hal/ports/STM32/STM32F4xx/ext_lld_isr.h170
-rw-r--r--os/hal/ports/STM32/STM32F4xx/hal_lld.c252
-rw-r--r--os/hal/ports/STM32/STM32F4xx/hal_lld.h1393
-rw-r--r--os/hal/ports/STM32/STM32F4xx/platform.mk33
-rw-r--r--os/hal/ports/STM32/STM32F4xx/stm32_dma.c527
-rw-r--r--os/hal/ports/STM32/STM32F4xx/stm32_dma.h461
-rw-r--r--os/hal/ports/STM32/STM32F4xx/stm32_isr.h150
-rw-r--r--os/hal/ports/STM32/STM32F4xx/stm32_rcc.h1382
-rw-r--r--os/hal/ports/STM32/STM32F4xx/stm32_registry.h296
12 files changed, 5983 insertions, 0 deletions
diff --git a/os/hal/ports/STM32/STM32F4xx/adc_lld.c b/os/hal/ports/STM32/STM32F4xx/adc_lld.c
new file mode 100644
index 000000000..85cb485bc
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/adc_lld.c
@@ -0,0 +1,418 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/adc_lld.c
+ * @brief STM32F4xx/STM32F2xx ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define ADC1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN)
+
+#define ADC2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN)
+
+#define ADC3_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/** @brief ADC2 driver identifier.*/
+#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__)
+ADCDriver ADCD2;
+#endif
+
+/** @brief ADC3 driver identifier.*/
+#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__)
+ADCDriver ADCD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC DMA ISR service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \
+ defined(__DOXYGEN__)
+/**
+ * @brief ADC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(ADC1_2_3_IRQHandler) {
+ uint32_t sr;
+
+ OSAL_IRQ_PROLOGUE();
+
+#if STM32_ADC_USE_ADC1
+ sr = ADC1->SR;
+ ADC1->SR = 0;
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ if (ADCD1.grpp != NULL)
+ _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW);
+ }
+ /* TODO: Add here analog watchdog handling.*/
+#endif /* STM32_ADC_USE_ADC1 */
+
+#if STM32_ADC_USE_ADC2
+ sr = ADC2->SR;
+ ADC2->SR = 0;
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD2.dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ if (ADCD2.grpp != NULL)
+ _adc_isr_error_code(&ADCD2, ADC_ERR_OVERFLOW);
+ }
+ /* TODO: Add here analog watchdog handling.*/
+#endif /* STM32_ADC_USE_ADC2 */
+
+#if STM32_ADC_USE_ADC3
+ sr = ADC3->SR;
+ ADC3->SR = 0;
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD3.dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ if (ADCD3.grpp != NULL)
+ _adc_isr_error_code(&ADCD3, ADC_ERR_OVERFLOW);
+ }
+ /* TODO: Add here analog watchdog handling.*/
+#endif /* STM32_ADC_USE_ADC3 */
+
+ CH_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if STM32_ADC_USE_ADC1
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.adc = ADC1;
+ ADCD1.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC1_DMA_STREAM);
+ ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_ADC_USE_ADC2
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD2);
+ ADCD2.adc = ADC2;
+ ADCD2.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC2_DMA_STREAM);
+ ADCD2.dmamode = STM32_DMA_CR_CHSEL(ADC2_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_ADC_USE_ADC3
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD3);
+ ADCD3.adc = ADC3;
+ ADCD3.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC3_DMA_STREAM);
+ ADCD3.dmamode = STM32_DMA_CR_CHSEL(ADC3_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif
+
+ /* The shared vector is initialized on driver initialization and never
+ disabled.*/
+ nvicEnableVector(ADC_IRQn, STM32_ADC_IRQ_PRIORITY);
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ /* If in stopped state then enables the ADC and DMA clocks.*/
+ if (adcp->state == ADC_STOP) {
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp) {
+ bool b;
+ b = dmaStreamAllocate(adcp->dmastp,
+ STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(!b, "stream already allocated");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR);
+ rccEnableADC1(FALSE);
+ }
+#endif /* STM32_ADC_USE_ADC1 */
+
+#if STM32_ADC_USE_ADC2
+ if (&ADCD2 == adcp) {
+ bool b;
+ b = dmaStreamAllocate(adcp->dmastp,
+ STM32_ADC_ADC2_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(!b, "stream already allocated");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR);
+ rccEnableADC2(FALSE);
+ }
+#endif /* STM32_ADC_USE_ADC2 */
+
+#if STM32_ADC_USE_ADC3
+ if (&ADCD3 == adcp) {
+ bool b;
+ b = dmaStreamAllocate(adcp->dmastp,
+ STM32_ADC_ADC3_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(!b, "stream already allocated");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR);
+ rccEnableADC3(FALSE);
+ }
+#endif /* STM32_ADC_USE_ADC3 */
+
+ /* This is a common register but apparently it requires that at least one
+ of the ADCs is clocked in order to allow writing, see bug 3575297.*/
+ ADC->CCR = (ADC->CCR & (ADC_CCR_TSVREFE | ADC_CCR_VBATE)) |
+ (STM32_ADC_ADCPRE << 16);
+
+ /* ADC initial setup, starting the analog part here in order to reduce
+ the latency when starting a conversion.*/
+ adcp->adc->CR1 = 0;
+ adcp->adc->CR2 = 0;
+ adcp->adc->CR2 = ADC_CR2_ADON;
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ /* If in ready state then disables the ADC clock.*/
+ if (adcp->state == ADC_READY) {
+ dmaStreamRelease(adcp->dmastp);
+ adcp->adc->CR1 = 0;
+ adcp->adc->CR2 = 0;
+
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp)
+ rccDisableADC1(FALSE);
+#endif
+
+#if STM32_ADC_USE_ADC2
+ if (&ADCD2 == adcp)
+ rccDisableADC2(FALSE);
+#endif
+
+#if STM32_ADC_USE_ADC3
+ if (&ADCD3 == adcp)
+ rccDisableADC3(FALSE);
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t mode;
+ const ADCConversionGroup *grpp = adcp->grpp;
+
+ /* DMA setup.*/
+ mode = adcp->dmamode;
+ if (grpp->circular) {
+ mode |= STM32_DMA_CR_CIRC;
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ mode |= STM32_DMA_CR_HTIE;
+ }
+ }
+ dmaStreamSetMemory0(adcp->dmastp, adcp->samples);
+ dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+ dmaStreamSetMode(adcp->dmastp, mode);
+ dmaStreamEnable(adcp->dmastp);
+
+ /* ADC setup.*/
+ adcp->adc->SR = 0;
+ adcp->adc->SMPR1 = grpp->smpr1;
+ adcp->adc->SMPR2 = grpp->smpr2;
+ adcp->adc->SQR1 = grpp->sqr1;
+ adcp->adc->SQR2 = grpp->sqr2;
+ adcp->adc->SQR3 = grpp->sqr3;
+
+ /* ADC configuration and start, the start is performed using the method
+ specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/
+ adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN;
+ if ((grpp->cr2 & ADC_CR2_SWSTART) != 0)
+ adcp->adc->CR2 = grpp->cr2 | ADC_CR2_CONT | ADC_CR2_DMA |
+ ADC_CR2_DDS | ADC_CR2_ADON;
+ else
+ adcp->adc->CR2 = grpp->cr2 | ADC_CR2_DMA |
+ ADC_CR2_DDS | ADC_CR2_ADON;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ dmaStreamDisable(adcp->dmastp);
+ adcp->adc->CR1 = 0;
+ adcp->adc->CR2 = 0;
+ adcp->adc->CR2 = ADC_CR2_ADON;
+}
+
+/**
+ * @brief Enables the TSVREFE bit.
+ * @details The TSVREFE bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ */
+void adcSTM32EnableTSVREFE(void) {
+
+ ADC->CCR |= ADC_CCR_TSVREFE;
+}
+
+/**
+ * @brief Disables the TSVREFE bit.
+ * @details The TSVREFE bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ */
+void adcSTM32DisableTSVREFE(void) {
+
+ ADC->CCR &= ~ADC_CCR_TSVREFE;
+}
+
+/**
+ * @brief Enables the VBATE bit.
+ * @details The VBATE bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ */
+void adcSTM32EnableVBATE(void) {
+
+ ADC->CCR |= ADC_CCR_VBATE;
+}
+
+/**
+ * @brief Disables the VBATE bit.
+ * @details The VBATE bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ */
+void adcSTM32DisableVBATE(void) {
+
+ ADC->CCR &= ~ADC_CCR_VBATE;
+}
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/adc_lld.h b/os/hal/ports/STM32/STM32F4xx/adc_lld.h
new file mode 100644
index 000000000..6b6530a61
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/adc_lld.h
@@ -0,0 +1,563 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/adc_lld.h
+ * @brief STM32F4xx/STM32F2xx ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef _ADC_LLD_H_
+#define _ADC_LLD_H_
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Absolute Maximum Ratings
+ * @{
+ */
+/**
+ * @brief Minimum ADC clock frequency.
+ */
+#define STM32_ADCCLK_MIN 600000
+
+/**
+ * @brief Maximum ADC clock frequency.
+ */
+#if defined(STM32F4XX) || defined(__DOXYGEN__)
+#define STM32_ADCCLK_MAX 36000000
+#else
+#define STM32_ADCCLK_MAX 30000000
+#endif
+/** @} */
+
+/**
+ * @name Triggers selection
+ * @{
+ */
+#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */
+/** @} */
+
+/**
+ * @name ADC clock divider settings
+ * @{
+ */
+#define ADC_CCR_ADCPRE_DIV2 0
+#define ADC_CCR_ADCPRE_DIV4 1
+#define ADC_CCR_ADCPRE_DIV6 2
+#define ADC_CCR_ADCPRE_DIV8 3
+/** @} */
+
+/**
+ * @name Available analog channels
+ * @{
+ */
+#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */
+#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */
+#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */
+#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */
+#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */
+#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */
+#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */
+#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */
+#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */
+#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */
+#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */
+#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */
+#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */
+#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */
+#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */
+#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */
+#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.
+ @note Available onADC1 only. */
+#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference.
+ @note Available onADC1 only. */
+#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT.
+ @note Available onADC1 only. */
+/** @} */
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#define ADC_SAMPLE_3 0 /**< @brief 3 cycles sampling time. */
+#define ADC_SAMPLE_15 1 /**< @brief 15 cycles sampling time. */
+#define ADC_SAMPLE_28 2 /**< @brief 28 cycles sampling time. */
+#define ADC_SAMPLE_56 3 /**< @brief 56 cycles sampling time. */
+#define ADC_SAMPLE_84 4 /**< @brief 84 cycles sampling time. */
+#define ADC_SAMPLE_112 5 /**< @brief 112 cycles sampling time. */
+#define ADC_SAMPLE_144 6 /**< @brief 144 cycles sampling time. */
+#define ADC_SAMPLE_480 7 /**< @brief 480 cycles sampling time. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief ADC common clock divider.
+ * @note This setting is influenced by the VDDA voltage and other
+ * external conditions, please refer to the datasheet for more
+ * info.<br>
+ * See section 5.3.20 "12-bit ADC characteristics".
+ */
+#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV2
+#endif
+
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC1 FALSE
+#endif
+
+/**
+ * @brief ADC2 driver enable switch.
+ * @details If set to @p TRUE the support for ADC2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC2 FALSE
+#endif
+
+/**
+ * @brief ADC3 driver enable switch.
+ * @details If set to @p TRUE the support for ADC3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC3 FALSE
+#endif
+
+/**
+ * @brief DMA stream used for ADC1 operations.
+ */
+#if !defined(STM32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
+#endif
+
+/**
+ * @brief DMA stream used for ADC2 operations.
+ */
+#if !defined(STM32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
+#endif
+
+/**
+ * @brief DMA stream used for ADC3 operations.
+ */
+#if !defined(STM32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
+#endif
+
+/**
+ * @brief ADC1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC3 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC interrupt priority level setting.
+ * @note This setting is shared among ADC1, ADC2 and ADC3 because
+ * all ADCs share the same vector.
+ */
+#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC1 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC2 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC3 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2
+#error "ADC2 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3
+#error "ADC3 not present in the selected device"
+#endif
+
+#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3
+#error "ADC driver activated but no ADC peripheral assigned"
+#endif
+
+#if STM32_ADC_USE_ADC1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK)
+#error "invalid DMA stream associated to ADC1"
+#endif
+
+#if STM32_ADC_USE_ADC2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK)
+#error "invalid DMA stream associated to ADC2"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK)
+#error "invalid DMA stream associated to ADC3"
+#endif
+
+/* ADC clock related settings and checks.*/
+#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2
+#define STM32_ADCCLK (STM32_PCLK2 / 2)
+#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4
+#define STM32_ADCCLK (STM32_PCLK2 / 4)
+#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV6
+#define STM32_ADCCLK (STM32_PCLK2 / 6)
+#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV8
+#define STM32_ADCCLK (STM32_PCLK2 / 8)
+#else
+#error "invalid STM32_ADC_ADCPRE value specified"
+#endif
+
+#if (STM32_ADCCLK < STM32_ADCCLK_MIN) || (STM32_ADCCLK > STM32_ADCCLK_MAX)
+#error "STM32_ADCCLK outside acceptable range (STM32_ADCCLK_MIN...STM32_ADCCLK_MAX)"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+typedef uint16_t adcsample_t;
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint16_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ ADC_ERR_OVERFLOW = 1 /**< ADC overflow condition. */
+} adcerror_t;
+
+/**
+ * @brief Type of a structure representing an ADC driver.
+ */
+typedef struct ADCDriver ADCDriver;
+
+/**
+ * @brief ADC notification callback type.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ * @param[in] buffer pointer to the most recent samples data
+ * @param[in] n number of buffer rows available starting from @p buffer
+ */
+typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n);
+
+/**
+ * @brief ADC error callback type.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ * @param[in] err ADC error code
+ */
+typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err);
+
+/**
+ * @brief Conversion group configuration structure.
+ * @details This implementation-dependent structure describes a conversion
+ * operation.
+ * @note The use of this configuration structure requires knowledge of
+ * STM32 ADC cell registers interface, please refer to the STM32
+ * reference manual for details.
+ */
+typedef struct {
+ /**
+ * @brief Enables the circular buffer mode for the group.
+ */
+ bool circular;
+ /**
+ * @brief Number of the analog channels belonging to the conversion group.
+ */
+ adc_channels_num_t num_channels;
+ /**
+ * @brief Callback function associated to the group or @p NULL.
+ */
+ adccallback_t end_cb;
+ /**
+ * @brief Error callback or @p NULL.
+ */
+ adcerrorcallback_t error_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief ADC CR1 register initialization data.
+ * @note All the required bits must be defined into this field except
+ * @p ADC_CR1_SCAN that is enforced inside the driver.
+ */
+ uint32_t cr1;
+ /**
+ * @brief ADC CR2 register initialization data.
+ * @note All the required bits must be defined into this field except
+ * @p ADC_CR2_DMA, @p ADC_CR2_CONT and @p ADC_CR2_ADON that are
+ * enforced inside the driver.
+ */
+ uint32_t cr2;
+ /**
+ * @brief ADC SMPR1 register initialization data.
+ * @details In this field must be specified the sample times for channels
+ * 10...18.
+ */
+ uint32_t smpr1;
+ /**
+ * @brief ADC SMPR2 register initialization data.
+ * @details In this field must be specified the sample times for channels
+ * 0...9.
+ */
+ uint32_t smpr2;
+ /**
+ * @brief ADC SQR1 register initialization data.
+ * @details Conversion group sequence 13...16 + sequence length.
+ */
+ uint32_t sqr1;
+ /**
+ * @brief ADC SQR2 register initialization data.
+ * @details Conversion group sequence 7...12.
+ */
+ uint32_t sqr2;
+ /**
+ * @brief ADC SQR3 register initialization data.
+ * @details Conversion group sequence 1...6.
+ */
+ uint32_t sqr3;
+} ADCConversionGroup;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ uint32_t dummy;
+} ADCConfig;
+
+/**
+ * @brief Structure representing an ADC driver.
+ */
+struct ADCDriver {
+ /**
+ * @brief Driver state.
+ */
+ adcstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const ADCConfig *config;
+ /**
+ * @brief Current samples buffer pointer or @p NULL.
+ */
+ adcsample_t *samples;
+ /**
+ * @brief Current samples buffer depth or @p 0.
+ */
+ size_t depth;
+ /**
+ * @brief Current conversion group pointer or @p NULL.
+ */
+ const ADCConversionGroup *grpp;
+#if ADC_USE_WAIT || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* ADC_USE_MUTUAL_EXCLUSION */
+#if defined(ADC_DRIVER_EXT_FIELDS)
+ ADC_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the ADCx registers block.
+ */
+ ADC_TypeDef *adc;
+ /**
+ * @brief Pointer to associated DMA channel.
+ */
+ const stm32_dma_stream_t *dmastp;
+ /**
+ * @brief DMA mode bit mask.
+ */
+ uint32_t dmamode;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Sequences building helper macros
+ * @{
+ */
+/**
+ * @brief Number of channels in a conversion sequence.
+ */
+#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
+
+#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
+#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
+#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
+#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
+#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
+#define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
+
+#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
+#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
+#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
+#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
+#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
+#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
+
+#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
+#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
+#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
+#define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
+/** @} */
+
+/**
+ * @name Sampling rate settings helper macros
+ * @{
+ */
+#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
+#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
+#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
+#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
+#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
+#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
+#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
+#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
+#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
+#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
+
+#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
+#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
+#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
+#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
+#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
+#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
+#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor
+ sampling time. */
+#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference
+ sampling time. */
+#define ADC_SMPR1_SMP_VBAT(n) ((n) << 24) /**< @brief VBAT sampling time. */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#if STM32_ADC_USE_ADC2 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD2;
+#endif
+
+#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+ void adcSTM32EnableTSVREFE(void);
+ void adcSTM32DisableTSVREFE(void);
+ void adcSTM32EnableVBATE(void);
+ void adcSTM32DisableVBATE(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* _ADC_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/ext_lld_isr.c b/os/hal/ports/STM32/STM32F4xx/ext_lld_isr.c
new file mode 100644
index 000000000..dd1491557
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/ext_lld_isr.c
@@ -0,0 +1,338 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/ext_lld_isr.c
+ * @brief STM32F4xx/STM32F2xx EXT subsystem low level driver ISR code.
+ *
+ * @addtogroup EXT
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_EXT || defined(__DOXYGEN__)
+
+#include "ext_lld_isr.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief EXTI[0] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector58) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 0);
+ EXTD1.config->channels[0].cb(&EXTD1, 0);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[1] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector5C) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 1);
+ EXTD1.config->channels[1].cb(&EXTD1, 1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[2] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector60) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 2);
+ EXTD1.config->channels[2].cb(&EXTD1, 2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[3] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector64) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 3);
+ EXTD1.config->channels[3].cb(&EXTD1, 3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[4] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector68) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 4);
+ EXTD1.config->channels[4].cb(&EXTD1, 4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[5]...EXTI[9] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector9C) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ pr = EXTI->PR & ((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9));
+ EXTI->PR = pr;
+ if (pr & (1 << 5))
+ EXTD1.config->channels[5].cb(&EXTD1, 5);
+ if (pr & (1 << 6))
+ EXTD1.config->channels[6].cb(&EXTD1, 6);
+ if (pr & (1 << 7))
+ EXTD1.config->channels[7].cb(&EXTD1, 7);
+ if (pr & (1 << 8))
+ EXTD1.config->channels[8].cb(&EXTD1, 8);
+ if (pr & (1 << 9))
+ EXTD1.config->channels[9].cb(&EXTD1, 9);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[10]...EXTI[15] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(VectorE0) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ pr = EXTI->PR & ((1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) |
+ (1 << 15));
+ EXTI->PR = pr;
+ if (pr & (1 << 10))
+ EXTD1.config->channels[10].cb(&EXTD1, 10);
+ if (pr & (1 << 11))
+ EXTD1.config->channels[11].cb(&EXTD1, 11);
+ if (pr & (1 << 12))
+ EXTD1.config->channels[12].cb(&EXTD1, 12);
+ if (pr & (1 << 13))
+ EXTD1.config->channels[13].cb(&EXTD1, 13);
+ if (pr & (1 << 14))
+ EXTD1.config->channels[14].cb(&EXTD1, 14);
+ if (pr & (1 << 15))
+ EXTD1.config->channels[15].cb(&EXTD1, 15);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[16] interrupt handler (PVD).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector44) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 16);
+ EXTD1.config->channels[16].cb(&EXTD1, 16);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[17] interrupt handler (RTC_ALARM).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(VectorE4) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 17);
+ EXTD1.config->channels[17].cb(&EXTD1, 17);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[18] interrupt handler (OTG_FS_WKUP).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(VectorE8) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 18);
+ EXTD1.config->channels[18].cb(&EXTD1, 18);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[19] interrupt handler (ETH_WKUP).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector138) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 19);
+ EXTD1.config->channels[19].cb(&EXTD1, 19);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[20] interrupt handler (OTG_HS_WKUP).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector170) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 20);
+ EXTD1.config->channels[20].cb(&EXTD1, 20);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[21] interrupt handler (TAMPER_STAMP).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector48) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 21);
+ EXTD1.config->channels[21].cb(&EXTD1, 21);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief EXTI[22] interrupt handler (RTC_WKUP).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector4C) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ EXTI->PR = (1 << 22);
+ EXTD1.config->channels[22].cb(&EXTD1, 22);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables EXTI IRQ sources.
+ *
+ * @notapi
+ */
+void ext_lld_exti_irq_enable(void) {
+
+ nvicEnableVector(EXTI0_IRQn, STM32_EXT_EXTI0_IRQ_PRIORITY);
+ nvicEnableVector(EXTI1_IRQn, STM32_EXT_EXTI1_IRQ_PRIORITY);
+ nvicEnableVector(EXTI2_IRQn, STM32_EXT_EXTI2_IRQ_PRIORITY);
+ nvicEnableVector(EXTI3_IRQn, STM32_EXT_EXTI3_IRQ_PRIORITY);
+ nvicEnableVector(EXTI4_IRQn, STM32_EXT_EXTI4_IRQ_PRIORITY);
+ nvicEnableVector(EXTI9_5_IRQn, STM32_EXT_EXTI5_9_IRQ_PRIORITY);
+ nvicEnableVector(EXTI15_10_IRQn, STM32_EXT_EXTI10_15_IRQ_PRIORITY);
+ nvicEnableVector(PVD_IRQn, STM32_EXT_EXTI16_IRQ_PRIORITY);
+ nvicEnableVector(RTC_Alarm_IRQn, STM32_EXT_EXTI17_IRQ_PRIORITY);
+ nvicEnableVector(OTG_FS_WKUP_IRQn, STM32_EXT_EXTI18_IRQ_PRIORITY);
+ nvicEnableVector(ETH_WKUP_IRQn, STM32_EXT_EXTI19_IRQ_PRIORITY);
+ nvicEnableVector(OTG_HS_WKUP_IRQn, STM32_EXT_EXTI20_IRQ_PRIORITY);
+ nvicEnableVector(TAMP_STAMP_IRQn, STM32_EXT_EXTI21_IRQ_PRIORITY);
+ nvicEnableVector(RTC_WKUP_IRQn, STM32_EXT_EXTI22_IRQ_PRIORITY);
+}
+
+/**
+ * @brief Disables EXTI IRQ sources.
+ *
+ * @notapi
+ */
+void ext_lld_exti_irq_disable(void) {
+
+ nvicDisableVector(EXTI0_IRQn);
+ nvicDisableVector(EXTI1_IRQn);
+ nvicDisableVector(EXTI2_IRQn);
+ nvicDisableVector(EXTI3_IRQn);
+ nvicDisableVector(EXTI4_IRQn);
+ nvicDisableVector(EXTI9_5_IRQn);
+ nvicDisableVector(EXTI15_10_IRQn);
+ nvicDisableVector(PVD_IRQn);
+ nvicDisableVector(RTC_Alarm_IRQn);
+ nvicDisableVector(OTG_FS_WKUP_IRQn);
+ nvicDisableVector(ETH_WKUP_IRQn);
+ nvicDisableVector(OTG_HS_WKUP_IRQn);
+ nvicDisableVector(TAMP_STAMP_IRQn);
+ nvicDisableVector(RTC_WKUP_IRQn);
+}
+
+#endif /* HAL_USE_EXT */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/ext_lld_isr.h b/os/hal/ports/STM32/STM32F4xx/ext_lld_isr.h
new file mode 100644
index 000000000..33e8e0be1
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/ext_lld_isr.h
@@ -0,0 +1,170 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/ext_lld_isr.h
+ * @brief STM32F4xx/STM32F2xx EXT subsystem low level driver ISR header.
+ *
+ * @addtogroup EXT
+ * @{
+ */
+
+#ifndef _EXT_LLD_ISR_H_
+#define _EXT_LLD_ISR_H_
+
+#if HAL_USE_EXT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief EXTI0 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI0_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI1 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI1_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI2 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI2_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI3 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI3_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI4 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI4_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI9..5 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI5_9_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI15..10 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI10_15_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI16 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI16_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI16_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI17 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI17_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI17_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI18 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI18_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI18_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI19 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI19_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI19_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI20 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI20_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI20_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI21 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI21_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI21_IRQ_PRIORITY 6
+#endif
+
+/**
+ * @brief EXTI22 interrupt priority level setting.
+ */
+#if !defined(STM32_EXT_EXTI22_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_EXT_EXTI22_IRQ_PRIORITY 6
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void ext_lld_exti_irq_enable(void);
+ void ext_lld_exti_irq_disable(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_EXT */
+
+#endif /* _EXT_LLD_ISR_H_ */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld.c b/os/hal/ports/STM32/STM32F4xx/hal_lld.c
new file mode 100644
index 000000000..7aeb67297
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/hal_lld.c
@@ -0,0 +1,252 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/hal_lld.c
+ * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the backup domain.
+ * @note WARNING! Changing clock source impossible without resetting
+ * of the whole BKP domain.
+ */
+static void hal_lld_backup_domain_init(void) {
+
+ /* Backup domain access enabled and left open.*/
+ PWR->CR |= PWR_CR_DBP;
+
+ /* Reset BKP domain if different clock source selected.*/
+ if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) {
+ /* Backup domain reset.*/
+ RCC->BDCR = RCC_BDCR_BDRST;
+ RCC->BDCR = 0;
+ }
+
+#if STM32_LSE_ENABLED
+#if defined(STM32_LSE_BYPASS)
+ /* LSE Bypass.*/
+ RCC->BDCR |= RCC_BDCR_LSEON | RCC_BDCR_LSEBYP;
+#else
+ /* No LSE Bypass.*/
+ RCC->BDCR |= RCC_BDCR_LSEON;
+#endif
+ while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+ ; /* Waits until LSE is stable. */
+#endif
+
+#if HAL_USE_RTC
+ /* If the backup domain hasn't been initialized yet then proceed with
+ initialization.*/
+ if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
+ /* Selects clock source.*/
+ RCC->BDCR |= STM32_RTCSEL;
+
+ /* RTC clock enabled.*/
+ RCC->BDCR |= RCC_BDCR_RTCEN;
+ }
+#endif /* HAL_USE_RTC */
+
+#if STM32_BKPRAM_ENABLE
+ rccEnableBKPSRAM(false);
+
+ PWR->CSR |= PWR_CSR_BRE;
+ while ((PWR->CSR & PWR_CSR_BRR) == 0)
+ ; /* Waits until the regulator is stable */
+#else
+ PWR->CSR &= ~PWR_CSR_BRE;
+#endif /* STM32_BKPRAM_ENABLE */
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+
+ /* Reset of all peripherals. AHB3 is not reseted because it could have
+ been initialized in the board initialization file (board.c).*/
+ rccResetAHB1(~0);
+ rccResetAHB2(~0);
+ rccResetAPB1(~RCC_APB1RSTR_PWRRST);
+ rccResetAPB2(~0);
+
+ /* PWR clock enabled.*/
+ rccEnablePWRInterface(FALSE);
+
+ /* Initializes the backup domain.*/
+ hal_lld_backup_domain_init();
+
+#if defined(STM32_DMA_REQUIRED)
+ dmaInit();
+#endif
+
+ /* Programmable voltage detector enable.*/
+#if STM32_PVD_ENABLE
+ PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK);
+#endif /* STM32_PVD_ENABLE */
+}
+
+/**
+ * @brief STM32F2xx clocks and PLL initialization.
+ * @note All the involved constants come from the file @p board.h.
+ * @note This function should be invoked just after the system reset.
+ *
+ * @special
+ */
+void stm32_clock_init(void) {
+
+#if !STM32_NO_INIT
+ /* PWR clock enable.*/
+ RCC->APB1ENR = RCC_APB1ENR_PWREN;
+
+ /* PWR initialization.*/
+#if defined(STM32F4XX) || defined(__DOXYGEN__)
+ PWR->CR = STM32_VOS;
+#else
+ PWR->CR = 0;
+#endif
+
+ /* HSI setup, it enforces the reset situation in order to handle possible
+ problems with JTAG probes and re-initializations.*/
+ RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */
+ while (!(RCC->CR & RCC_CR_HSIRDY))
+ ; /* Wait until HSI is stable. */
+ RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; /* CR Reset value. */
+ RCC->CFGR = 0; /* CFGR reset value. */
+ while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
+ ; /* Waits until HSI is selected. */
+
+#if STM32_HSE_ENABLED
+ /* HSE activation.*/
+#if defined(STM32_HSE_BYPASS)
+ /* HSE Bypass.*/
+ RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP;
+#else
+ /* No HSE Bypass.*/
+ RCC->CR |= RCC_CR_HSEON;
+#endif
+ while ((RCC->CR & RCC_CR_HSERDY) == 0)
+ ; /* Waits until HSE is stable. */
+#endif
+
+#if STM32_LSI_ENABLED
+ /* LSI activation.*/
+ RCC->CSR |= RCC_CSR_LSION;
+ while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
+ ; /* Waits until LSI is stable. */
+#endif
+
+#if STM32_ACTIVATE_PLL
+ /* PLL activation.*/
+ RCC->PLLCFGR = STM32_PLLQ | STM32_PLLSRC | STM32_PLLP | STM32_PLLN |
+ STM32_PLLM;
+ RCC->CR |= RCC_CR_PLLON;
+
+ /* Synchronization with voltage regulator stabilization.*/
+#if defined(STM32F4XX)
+ while ((PWR->CSR & PWR_CSR_VOSRDY) == 0)
+ ; /* Waits until power regulator is stable. */
+
+#if STM32_OVERDRIVE_REQUIRED
+ /* Overdrive activation performed after activating the PLL in order to save
+ time as recommended in RM in "Entering Over-drive mode" paragraph.*/
+ PWR->CR |= PWR_CR_ODEN;
+ while (!(PWR->CSR & PWR_CSR_ODRDY))
+ ;
+ PWR->CR |= PWR_CR_ODSWEN;
+ while (!(PWR->CSR & PWR_CSR_ODSWRDY))
+ ;
+#endif /* STM32_OVERDRIVE_REQUIRED */
+#endif /* defined(STM32F4XX) */
+
+ /* Waiting for PLL lock.*/
+ while (!(RCC->CR & RCC_CR_PLLRDY))
+ ;
+#endif /* STM32_OVERDRIVE_REQUIRED */
+
+#if STM32_ACTIVATE_PLLI2S
+ /* PLLI2S activation.*/
+ RCC->PLLI2SCFGR = STM32_PLLI2SR | STM32_PLLI2SN;
+ RCC->CR |= RCC_CR_PLLI2SON;
+
+ /* Waiting for PLL lock.*/
+ while (!(RCC->CR & RCC_CR_PLLI2SRDY))
+ ;
+#endif
+
+ /* Other clock-related settings (dividers, MCO etc).*/
+ RCC->CFGR = STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL |
+ STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
+
+ /* Flash setup.*/
+#if defined(STM32_USE_REVISION_A_FIX)
+ /* Some old revisions of F4x MCUs randomly crashes with compiler
+ optimizations enabled AND flash caches enabled. */
+ if ((DBGMCU->IDCODE == 0x20006411) && (SCB->CPUID == 0x410FC241))
+ FLASH->ACR = FLASH_ACR_PRFTEN | STM32_FLASHBITS;
+ else
+ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |
+ FLASH_ACR_DCEN | STM32_FLASHBITS;
+#else
+ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |
+ FLASH_ACR_DCEN | STM32_FLASHBITS;
+#endif
+
+ /* Switching to the configured clock source if it is different from MSI.*/
+#if (STM32_SW != STM32_SW_HSI)
+ RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */
+ while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
+ ;
+#endif
+#endif /* STM32_NO_INIT */
+
+ /* SYSCFG clock enabled here because it is a multi-functional unit shared
+ among multiple drivers.*/
+ rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE);
+}
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/hal_lld.h b/os/hal/ports/STM32/STM32F4xx/hal_lld.h
new file mode 100644
index 000000000..c7f9ed864
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/hal_lld.h
@@ -0,0 +1,1393 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/hal_lld.h
+ * @brief STM32F4xx/STM32F2xx HAL subsystem low level driver header.
+ * @pre This module requires the following macros to be defined in the
+ * @p board.h file:
+ * - STM32_LSECLK.
+ * - STM32_LSE_BYPASS (optionally).
+ * - STM32_HSECLK.
+ * - STM32_HSE_BYPASS (optionally).
+ * - STM32_VDD (as hundredths of Volt).
+ * .
+ * One of the following macros must also be defined:
+ * - STM32F2XX for High-performance STM32 F-2 devices.
+ * - STM32F401xx for High-performance STM32 F-4 devices.
+ * - STM32F40_41xxx for High-performance STM32 F-4 devices.
+ * - STM32F427_437xx for High-performance STM32 F-4 devices.
+ * - STM32F429_439xx for High-performance STM32 F-4 devices.
+ * .
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef _HAL_LLD_H_
+#define _HAL_LLD_H_
+
+#include "stm32_registry.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Defines the support for realtime counters in the HAL.
+ */
+#define HAL_IMPLEMENTS_COUNTERS TRUE
+
+/**
+ * @name Platform identification macros
+ * @{
+ */
+#if defined(STM32F429_439xx) || defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32F429/F439 High Performance with DSP and FPU"
+#define STM32F4XX
+
+#elif defined(STM32F427_437xx)
+#define PLATFORM_NAME "STM32F427/F437 High Performance with DSP and FPU"
+#define STM32F4XX
+
+#elif defined(STM32F40_41xxx)
+#define PLATFORM_NAME "STM32F407/F417 High Performance with DSP and FPU"
+#define STM32F4XX
+
+#elif defined(STM32F401xx)
+#define PLATFORM_NAME "STM32F401 High Performance with DSP and FPU"
+#define STM32F4XX
+
+#elif defined(STM32F2XX)
+#define PLATFORM_NAME "STM32F2xx High Performance"
+
+#else
+#error "STM32F2xx/F4xx device not specified"
+#endif
+/** @} */
+
+/**
+ * @name Absolute Maximum Ratings
+ * @{
+ */
+/**
+ * @name Absolute Maximum Ratings
+ * @{
+ */
+#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Absolute maximum system clock.
+ */
+#define STM32_SYSCLK_MAX 180000000
+
+/**
+ * @brief Maximum HSE clock frequency.
+ */
+#define STM32_HSECLK_MAX 26000000
+
+/**
+ * @brief Maximum HSE clock frequency using an external source.
+ */
+#define STM32_HSECLK_BYP_MAX 50000000
+
+/**
+ * @brief Minimum HSE clock frequency.
+ */
+#define STM32_HSECLK_MIN 4000000
+
+/**
+ * @brief Minimum HSE clock frequency.
+ */
+#define STM32_HSECLK_BYP_MIN 1000000
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSECLK_MAX 32768
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSECLK_BYP_MAX 1000000
+
+/**
+ * @brief Minimum LSE clock frequency.
+ */
+#define STM32_LSECLK_MIN 32768
+
+/**
+ * @brief Maximum PLLs input clock frequency.
+ */
+#define STM32_PLLIN_MAX 2100000
+
+/**
+ * @brief Minimum PLLs input clock frequency.
+ */
+#define STM32_PLLIN_MIN 950000
+
+/**
+ * @brief Maximum PLLs VCO clock frequency.
+ */
+#define STM32_PLLVCO_MAX 432000000
+
+/**
+ * @brief Maximum PLLs VCO clock frequency.
+ */
+#define STM32_PLLVCO_MIN 192000000
+
+/**
+ * @brief Maximum PLL output clock frequency.
+ */
+#define STM32_PLLOUT_MAX 180000000
+
+/**
+ * @brief Minimum PLL output clock frequency.
+ */
+#define STM32_PLLOUT_MIN 24000000
+
+/**
+ * @brief Maximum APB1 clock frequency.
+ */
+#define STM32_PCLK1_MAX (STM32_PLLOUT_MAX /4)
+
+/**
+ * @brief Maximum APB2 clock frequency.
+ */
+#define STM32_PCLK2_MAX (STM32_PLLOUT_MAX / 2)
+
+/**
+ * @brief Maximum SPI/I2S clock frequency.
+ */
+#define STM32_SPII2S_MAX 45000000
+#endif /* STM32F40_41xxx */
+
+#if defined(STM32F40_41xxx) || defined(__DOXYGEN__)
+#define STM32_SYSCLK_MAX 168000000
+#define STM32_HSECLK_MAX 26000000
+#define STM32_HSECLK_BYP_MAX 50000000
+#define STM32_HSECLK_MIN 4000000
+#define STM32_HSECLK_BYP_MIN 1000000
+#define STM32_LSECLK_MAX 32768
+#define STM32_LSECLK_BYP_MAX 1000000
+#define STM32_LSECLK_MIN 32768
+#define STM32_PLLIN_MAX 2100000
+#define STM32_PLLIN_MIN 950000
+#define STM32_PLLVCO_MAX 432000000
+#define STM32_PLLVCO_MIN 192000000
+#define STM32_PLLOUT_MAX 168000000
+#define STM32_PLLOUT_MIN 24000000
+#define STM32_PCLK1_MAX 42000000
+#define STM32_PCLK2_MAX 84000000
+#define STM32_SPII2S_MAX 42000000
+#endif /* STM32F40_41xxx */
+
+#if defined(STM32F401xx) || defined(__DOXYGEN__)
+#define STM32_SYSCLK_MAX 84000000
+#define STM32_HSECLK_MAX 26000000
+#define STM32_HSECLK_BYP_MAX 50000000
+#define STM32_HSECLK_MIN 4000000
+#define STM32_HSECLK_BYP_MIN 1000000
+#define STM32_LSECLK_MAX 32768
+#define STM32_LSECLK_BYP_MAX 1000000
+#define STM32_LSECLK_MIN 32768
+#define STM32_PLLIN_MAX 2100000
+#define STM32_PLLIN_MIN 950000
+#define STM32_PLLVCO_MAX 432000000
+#define STM32_PLLVCO_MIN 192000000
+#define STM32_PLLOUT_MAX 84000000
+#define STM32_PLLOUT_MIN 24000000
+#define STM32_PCLK1_MAX 42000000
+#define STM32_PCLK2_MAX 84000000
+#define STM32_SPII2S_MAX 42000000
+#endif /* STM32F40_41xxx */
+
+#if defined(STM32F2XX)
+#define STM32_SYSCLK_MAX 120000000
+#define STM32_HSECLK_MAX 26000000
+#define STM32_HSECLK_BYP_MAX 26000000
+#define STM32_HSECLK_MIN 1000000
+#define STM32_HSECLK_BYP_MIN 1000000
+#define STM32_LSECLK_MAX 32768
+#define STM32_LSECLK_BYP_MAX 1000000
+#define STM32_LSECLK_MIN 32768
+#define STM32_PLLIN_MAX 2000000
+#define STM32_PLLIN_MIN 950000
+#define STM32_PLLVCO_MAX 432000000
+#define STM32_PLLVCO_MIN 192000000
+#define STM32_PLLOUT_MAX 120000000
+#define STM32_PLLOUT_MIN 24000000
+#define STM32_PCLK1_MAX 30000000
+#define STM32_PCLK2_MAX 60000000
+#define STM32_SPII2S_MAX 30000000
+#endif /* defined(STM32F2XX) */
+/** @} */
+
+/**
+ * @name Internal clock sources
+ * @{
+ */
+#define STM32_HSICLK 16000000 /**< High speed internal clock. */
+#define STM32_LSICLK 32000 /**< Low speed internal clock. */
+/** @} */
+
+/**
+ * @name PWR_CR register bits definitions
+ * @{
+ */
+#define STM32_VOS_SCALE3 (PWR_CR_VOS_0)
+#define STM32_VOS_SCALE2 (PWR_CR_VOS_1)
+#define STM32_VOS_SCALE1 (PWR_CR_VOS_1 | PWR_CR_VOS_0)
+#define STM32_PLS_MASK (7 << 5) /**< PLS bits mask. */
+#define STM32_PLS_LEV0 (0 << 5) /**< PVD level 0. */
+#define STM32_PLS_LEV1 (1 << 5) /**< PVD level 1. */
+#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 2. */
+#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 3. */
+#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 4. */
+#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 5. */
+#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 6. */
+#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 7. */
+/** @} */
+
+/**
+ * @name RCC_PLLCFGR register bits definitions
+ * @{
+ */
+#define STM32_PLLP_MASK (3 << 16) /**< PLLP mask. */
+#define STM32_PLLP_DIV2 (0 << 16) /**< PLL clock divided by 2. */
+#define STM32_PLLP_DIV4 (1 << 16) /**< PLL clock divided by 4. */
+#define STM32_PLLP_DIV6 (2 << 16) /**< PLL clock divided by 6. */
+#define STM32_PLLP_DIV8 (3 << 16) /**< PLL clock divided by 8. */
+
+#define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */
+#define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */
+/** @} */
+
+/**
+ * @name RCC_CFGR register bits definitions
+ * @{
+ */
+#define STM32_SW_MASK (3 << 0) /**< SW mask. */
+#define STM32_SW_HSI (0 << 0) /**< SYSCLK source is HSI. */
+#define STM32_SW_HSE (1 << 0) /**< SYSCLK source is HSE. */
+#define STM32_SW_PLL (2 << 0) /**< SYSCLK source is PLL. */
+
+#define STM32_HPRE_MASK (15 << 4) /**< HPRE mask. */
+#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */
+#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */
+#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */
+#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */
+#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */
+#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */
+#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */
+#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */
+#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */
+
+#define STM32_PPRE1_MASK (7 << 10) /**< PPRE1 mask. */
+#define STM32_PPRE1_DIV1 (0 << 10) /**< HCLK divided by 1. */
+#define STM32_PPRE1_DIV2 (4 << 10) /**< HCLK divided by 2. */
+#define STM32_PPRE1_DIV4 (5 << 10) /**< HCLK divided by 4. */
+#define STM32_PPRE1_DIV8 (6 << 10) /**< HCLK divided by 8. */
+#define STM32_PPRE1_DIV16 (7 << 10) /**< HCLK divided by 16. */
+
+#define STM32_PPRE2_MASK (7 << 13) /**< PPRE2 mask. */
+#define STM32_PPRE2_DIV1 (0 << 13) /**< HCLK divided by 1. */
+#define STM32_PPRE2_DIV2 (4 << 13) /**< HCLK divided by 2. */
+#define STM32_PPRE2_DIV4 (5 << 13) /**< HCLK divided by 4. */
+#define STM32_PPRE2_DIV8 (6 << 13) /**< HCLK divided by 8. */
+#define STM32_PPRE2_DIV16 (7 << 13) /**< HCLK divided by 16. */
+
+#define STM32_RTCPRE_MASK (31 << 16) /**< RTCPRE mask. */
+
+#define STM32_MCO1SEL_MASK (3 << 21) /**< MCO1 mask. */
+#define STM32_MCO1SEL_HSI (0 << 21) /**< HSI clock on MCO1 pin. */
+#define STM32_MCO1SEL_LSE (1 << 21) /**< LSE clock on MCO1 pin. */
+#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */
+#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */
+
+#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */
+#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */
+#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */
+
+#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */
+#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */
+#define STM32_MCO1PRE_DIV2 (4 << 24) /**< MCO1 divided by 2. */
+#define STM32_MCO1PRE_DIV3 (5 << 24) /**< MCO1 divided by 3. */
+#define STM32_MCO1PRE_DIV4 (6 << 24) /**< MCO1 divided by 4. */
+#define STM32_MCO1PRE_DIV5 (7 << 24) /**< MCO1 divided by 5. */
+
+#define STM32_MCO2PRE_MASK (7 << 27) /**< MCO2PRE mask. */
+#define STM32_MCO2PRE_DIV1 (0 << 27) /**< MCO2 divided by 1. */
+#define STM32_MCO2PRE_DIV2 (4 << 27) /**< MCO2 divided by 2. */
+#define STM32_MCO2PRE_DIV3 (5 << 27) /**< MCO2 divided by 3. */
+#define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */
+#define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */
+
+#define STM32_MCO2SEL_MASK (3U << 30) /**< MCO2 mask. */
+#define STM32_MCO2SEL_SYSCLK (0U << 30) /**< SYSCLK clock on MCO2 pin. */
+#define STM32_MCO2SEL_PLLI2S (1U << 30) /**< PLLI2S clock on MCO2 pin. */
+#define STM32_MCO2SEL_HSE (2U << 30) /**< HSE clock on MCO2 pin. */
+#define STM32_MCO2SEL_PLL (3U << 30) /**< PLL clock on MCO2 pin. */
+
+#define STM32_RTC_NOCLOCK (0 << 8) /**< No clock. */
+#define STM32_RTC_LSE (1 << 8) /**< LSE used as RTC clock. */
+#define STM32_RTC_LSI (2 << 8) /**< LSI used as RTC clock. */
+#define STM32_RTC_HSE (3 << 8) /**< HSE divided by programmable
+ prescaler used as RTC clock*/
+
+/**
+ * @name RCC_PLLI2SCFGR register bits definitions
+ * @{
+ */
+#define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */
+#define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */
+/** @} */
+
+/**
+ * @name RCC_BDCR register bits definitions
+ * @{
+ */
+#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */
+#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */
+#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */
+#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */
+#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Disables the PWR/RCC initialization in the HAL.
+ */
+#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__)
+#define STM32_NO_INIT FALSE
+#endif
+
+/**
+ * @brief Enables or disables the programmable voltage detector.
+ */
+#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__)
+#define STM32_PVD_ENABLE FALSE
+#endif
+
+/**
+ * @brief Sets voltage level for programmable voltage detector.
+ */
+#if !defined(STM32_PLS) || defined(__DOXYGEN__)
+#define STM32_PLS STM32_PLS_LEV0
+#endif
+
+/**
+ * @brief Enables the backup RAM regulator.
+ */
+#if !defined(STM32_BKPRAM_ENABLE) || defined(__DOXYGEN__)
+#define STM32_BKPRAM_ENABLE FALSE
+#endif
+
+/**
+ * @brief Enables or disables the HSI clock source.
+ */
+#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSI_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the LSI clock source.
+ */
+#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSI_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the HSE clock source.
+ */
+#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSE_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the LSE clock source.
+ */
+#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSE_ENABLED FALSE
+#endif
+
+/**
+ * @brief USB/SDIO clock setting.
+ */
+#if !defined(STM32_CLOCK48_REQUIRED) || defined(__DOXYGEN__)
+#define STM32_CLOCK48_REQUIRED TRUE
+#endif
+
+/**
+ * @brief Main clock source selection.
+ * @note If the selected clock source is not the PLL then the PLL is not
+ * initialized and started.
+ * @note The default value is calculated for a 168MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_SW) || defined(__DOXYGEN__)
+#define STM32_SW STM32_SW_PLL
+#endif
+
+#if defined(STM32F4XX) || defined(__DOXYGEN__)
+/**
+ * @brief Clock source for the PLLs.
+ * @note This setting has only effect if the PLL is selected as the
+ * system clock source.
+ * @note The default value is calculated for a 168MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__)
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#endif
+
+/**
+ * @brief PLLM divider value.
+ * @note The allowed values are 2..63.
+ * @note The default value is calculated for a 168MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLM_VALUE 8
+#endif
+
+/**
+ * @brief PLLN multiplier value.
+ * @note The allowed values are 192..432.
+ * @note The default value is calculated for a 168MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLN_VALUE 336
+#endif
+
+/**
+ * @brief PLLP divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ * @note The default value is calculated for a 168MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLP_VALUE 2
+#endif
+
+/**
+ * @brief PLLQ multiplier value.
+ * @note The allowed values are 2..15.
+ * @note The default value is calculated for a 168MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLQ_VALUE 7
+#endif
+
+#else /* !defined(STM32F4XX) */
+/**
+ * @brief Clock source for the PLLs.
+ * @note This setting has only effect if the PLL is selected as the
+ * system clock source.
+ * @note The default value is calculated for a 120MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__)
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#endif
+
+/**
+ * @brief PLLM divider value.
+ * @note The allowed values are 2..63.
+ * @note The default value is calculated for a 120MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLM_VALUE 8
+#endif
+
+/**
+ * @brief PLLN multiplier value.
+ * @note The allowed values are 192..432.
+ * @note The default value is calculated for a 120MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLN_VALUE 240
+#endif
+
+/**
+ * @brief PLLP divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ * @note The default value is calculated for a 120MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLP_VALUE 2
+#endif
+
+/**
+ * @brief PLLQ multiplier value.
+ * @note The allowed values are 2..15.
+ * @note The default value is calculated for a 120MHz system clock from
+ * an external 8MHz HSE clock.
+ */
+#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLQ_VALUE 5
+#endif
+#endif /* !defined(STM32F4XX) */
+
+/**
+ * @brief AHB prescaler value.
+ */
+#if !defined(STM32_HPRE) || defined(__DOXYGEN__)
+#define STM32_HPRE STM32_HPRE_DIV1
+#endif
+
+/**
+ * @brief APB1 prescaler value.
+ */
+#if !defined(STM32_PPRE1) || defined(__DOXYGEN__)
+#define STM32_PPRE1 STM32_PPRE1_DIV4
+#endif
+
+/**
+ * @brief APB2 prescaler value.
+ */
+#if !defined(STM32_PPRE2) || defined(__DOXYGEN__)
+#define STM32_PPRE2 STM32_PPRE2_DIV2
+#endif
+
+/**
+ * @brief RTC clock source.
+ */
+#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__)
+#define STM32_RTCSEL STM32_RTCSEL_LSE
+#endif
+
+/**
+ * @brief RTC HSE prescaler value.
+ */
+#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__)
+#define STM32_RTCPRE_VALUE 8
+#endif
+
+/**
+ * @brief MC01 clock source value.
+ * @note The default value outputs HSI clock on MC01 pin.
+ */
+#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__)
+#define STM32_MCO1SEL STM32_MCO1SEL_HSI
+#endif
+
+/**
+ * @brief MC01 prescaler value.
+ * @note The default value outputs HSI clock on MC01 pin.
+ */
+#if !defined(STM32_MCO1PRE) || defined(__DOXYGEN__)
+#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
+#endif
+
+/**
+ * @brief MC02 clock source value.
+ * @note The default value outputs SYSCLK / 5 on MC02 pin.
+ */
+#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__)
+#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
+#endif
+
+/**
+ * @brief MC02 prescaler value.
+ * @note The default value outputs SYSCLK / 5 on MC02 pin.
+ */
+#if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__)
+#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
+#endif
+
+/**
+ * @brief I2S clock source.
+ */
+#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__)
+#define STM32_I2SSRC STM32_I2SSRC_CKIN
+#endif
+
+/**
+ * @brief PLLI2SN multiplier value.
+ * @note The allowed values are 192..432.
+ */
+#if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLI2SN_VALUE 192
+#endif
+
+/**
+ * @brief PLLI2SR multiplier value.
+ * @note The allowed values are 2..7.
+ */
+#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLI2SR_VALUE 5
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if defined(STM32F4XX) || defined(__DOXYGEN__)
+/*
+ * Configuration-related checks.
+ */
+#if !defined(STM32F4xx_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32F4xx_MCUCONF not defined"
+#endif
+
+#else /* !defined(STM32F4XX) */
+/*
+ * Configuration-related checks.
+ */
+#if !defined(STM32F2xx_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32F2xx_MCUCONF not defined"
+#endif
+#endif /* !defined(STM32F4XX) */
+
+/**
+ * @brief Maximum frequency thresholds and wait states for flash access.
+ * @note The values are valid for 2.7V to 3.6V supply range.
+ */
+#if defined(STM32F429_439xx) || defined(STM32F427_437xx) || \
+ defined(STM32F40_41xxx) || defined(__DOXYGEN__)
+#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__)
+#define STM32_0WS_THRESHOLD 30000000
+#define STM32_1WS_THRESHOLD 60000000
+#define STM32_2WS_THRESHOLD 90000000
+#define STM32_3WS_THRESHOLD 120000000
+#define STM32_4WS_THRESHOLD 150000000
+#define STM32_5WS_THRESHOLD 180000000
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#define STM32_8WS_THRESHOLD 0
+#elif (STM32_VDD >= 240) && (STM32_VDD < 270)
+#define STM32_0WS_THRESHOLD 24000000
+#define STM32_1WS_THRESHOLD 48000000
+#define STM32_2WS_THRESHOLD 72000000
+#define STM32_3WS_THRESHOLD 96000000
+#define STM32_4WS_THRESHOLD 120000000
+#define STM32_5WS_THRESHOLD 144000000
+#define STM32_6WS_THRESHOLD 168000000
+#define STM32_7WS_THRESHOLD 180000000
+#define STM32_8WS_THRESHOLD 0
+#elif (STM32_VDD >= 210) && (STM32_VDD < 240)
+#define STM32_0WS_THRESHOLD 22000000
+#define STM32_1WS_THRESHOLD 44000000
+#define STM32_2WS_THRESHOLD 66000000
+#define STM32_3WS_THRESHOLD 88000000
+#define STM32_4WS_THRESHOLD 110000000
+#define STM32_5WS_THRESHOLD 132000000
+#define STM32_6WS_THRESHOLD 154000000
+#define STM32_7WS_THRESHOLD 176000000
+#define STM32_8WS_THRESHOLD 180000000
+#elif (STM32_VDD >= 180) && (STM32_VDD < 210)
+#define STM32_0WS_THRESHOLD 20000000
+#define STM32_1WS_THRESHOLD 40000000
+#define STM32_2WS_THRESHOLD 60000000
+#define STM32_3WS_THRESHOLD 80000000
+#define STM32_4WS_THRESHOLD 100000000
+#define STM32_5WS_THRESHOLD 120000000
+#define STM32_6WS_THRESHOLD 140000000
+#define STM32_7WS_THRESHOLD 168000000
+#define STM32_8WS_THRESHOLD 0
+#else
+#error "invalid VDD voltage specified"
+#endif
+
+#elif defined(STM32F401xx)
+#if (STM32_VDD >= 270) && (STM32_VDD <= 360)
+#define STM32_0WS_THRESHOLD 30000000
+#define STM32_1WS_THRESHOLD 60000000
+#define STM32_2WS_THRESHOLD 84000000
+#define STM32_3WS_THRESHOLD 0
+#define STM32_4WS_THRESHOLD 0
+#define STM32_5WS_THRESHOLD 0
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#define STM32_8WS_THRESHOLD 0
+#elif (STM32_VDD >= 240) && (STM32_VDD < 270)
+#define STM32_0WS_THRESHOLD 24000000
+#define STM32_1WS_THRESHOLD 48000000
+#define STM32_2WS_THRESHOLD 72000000
+#define STM32_3WS_THRESHOLD 84000000
+#define STM32_4WS_THRESHOLD 0
+#define STM32_5WS_THRESHOLD 0
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#define STM32_8WS_THRESHOLD 0
+#elif (STM32_VDD >= 210) && (STM32_VDD < 240)
+#define STM32_0WS_THRESHOLD 18000000
+#define STM32_1WS_THRESHOLD 36000000
+#define STM32_2WS_THRESHOLD 54000000
+#define STM32_3WS_THRESHOLD 72000000
+#define STM32_4WS_THRESHOLD 840000000
+#define STM32_5WS_THRESHOLD 0
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#define STM32_8WS_THRESHOLD 0
+#elif (STM32_VDD >= 180) && (STM32_VDD < 210)
+#define STM32_0WS_THRESHOLD 16000000
+#define STM32_1WS_THRESHOLD 32000000
+#define STM32_2WS_THRESHOLD 48000000
+#define STM32_3WS_THRESHOLD 64000000
+#define STM32_4WS_THRESHOLD 800000000
+#define STM32_5WS_THRESHOLD 840000000
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#define STM32_8WS_THRESHOLD 0
+#else
+#error "invalid VDD voltage specified"
+#endif
+
+#else /* STM32F2XX */
+#if (STM32_VDD >= 270) && (STM32_VDD <= 360)
+#define STM32_0WS_THRESHOLD 30000000
+#define STM32_1WS_THRESHOLD 60000000
+#define STM32_2WS_THRESHOLD 90000000
+#define STM32_3WS_THRESHOLD 120000000
+#define STM32_4WS_THRESHOLD 0
+#define STM32_5WS_THRESHOLD 0
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#elif (STM32_VDD >= 240) && (STM32_VDD < 270)
+#define STM32_0WS_THRESHOLD 24000000
+#define STM32_1WS_THRESHOLD 48000000
+#define STM32_2WS_THRESHOLD 72000000
+#define STM32_3WS_THRESHOLD 96000000
+#define STM32_4WS_THRESHOLD 120000000
+#define STM32_5WS_THRESHOLD 0
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#elif (STM32_VDD >= 210) && (STM32_VDD < 240)
+#define STM32_0WS_THRESHOLD 18000000
+#define STM32_1WS_THRESHOLD 36000000
+#define STM32_2WS_THRESHOLD 54000000
+#define STM32_3WS_THRESHOLD 72000000
+#define STM32_4WS_THRESHOLD 90000000
+#define STM32_5WS_THRESHOLD 108000000
+#define STM32_6WS_THRESHOLD 120000000
+#define STM32_7WS_THRESHOLD 0
+#elif (STM32_VDD >= 180) && (STM32_VDD < 210)
+#define STM32_0WS_THRESHOLD 16000000
+#define STM32_1WS_THRESHOLD 32000000
+#define STM32_2WS_THRESHOLD 48000000
+#define STM32_3WS_THRESHOLD 64000000
+#define STM32_4WS_THRESHOLD 80000000
+#define STM32_5WS_THRESHOLD 96000000
+#define STM32_6WS_THRESHOLD 112000000
+#define STM32_7WS_THRESHOLD 120000000
+#else
+#error "invalid VDD voltage specified"
+#endif
+#endif /* STM32F2XX */
+
+/*
+ * HSI related checks.
+ */
+#if STM32_HSI_ENABLED
+#else /* !STM32_HSI_ENABLED */
+
+#if STM32_SW == STM32_SW_HSI
+#error "HSI not enabled, required by STM32_SW"
+#endif
+
+#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI)
+#error "HSI not enabled, required by STM32_SW and STM32_PLLSRC"
+#endif
+
+#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \
+ ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSI))
+#error "HSI not enabled, required by STM32_MCO1SEL"
+#endif
+
+#if (STM32_MCO2SEL == STM32_MCO2SEL_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI)
+#error "HSI not enabled, required by STM32_MCO2SEL"
+#endif
+
+#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSI)
+#error "HSI not enabled, required by STM32_I2SSRC"
+#endif
+
+#endif /* !STM32_HSI_ENABLED */
+
+/*
+ * HSE related checks.
+ */
+#if STM32_HSE_ENABLED
+
+#if STM32_HSECLK == 0
+#error "HSE frequency not defined"
+#elif (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX)
+#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)"
+#endif
+
+#else /* !STM32_HSE_ENABLED */
+
+#if STM32_SW == STM32_SW_HSE
+#error "HSE not enabled, required by STM32_SW"
+#endif
+
+#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE)
+#error "HSE not enabled, required by STM32_SW and STM32_PLLSRC"
+#endif
+
+#if (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \
+ ((STM32_MCO1SEL == STM32_MCO1SEL_PLL) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSE))
+#error "HSE not enabled, required by STM32_MCO1SEL"
+#endif
+
+#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \
+ ((STM32_MCO2SEL == STM32_MCO2SEL_PLL) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSE))
+#error "HSE not enabled, required by STM32_MCO2SEL"
+#endif
+
+#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSE)
+#error "HSE not enabled, required by STM32_I2SSRC"
+#endif
+
+#if STM32_RTCSEL == STM32_RTCSEL_HSEDIV
+#error "HSE not enabled, required by STM32_RTCSEL"
+#endif
+
+#endif /* !STM32_HSE_ENABLED */
+
+/*
+ * LSI related checks.
+ */
+#if STM32_LSI_ENABLED
+#else /* !STM32_LSI_ENABLED */
+
+#if STM32_RTCSEL == STM32_RTCSEL_LSI
+#error "LSI not enabled, required by STM32_RTCSEL"
+#endif
+
+#endif /* !STM32_LSI_ENABLED */
+
+/*
+ * LSE related checks.
+ */
+#if STM32_LSE_ENABLED
+
+#if (STM32_LSECLK == 0)
+#error "LSE frequency not defined"
+#endif
+
+#if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX)
+#error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)"
+#endif
+
+#else /* !STM32_LSE_ENABLED */
+
+#if STM32_RTCSEL == STM32_RTCSEL_LSE
+#error "LSE not enabled, required by STM32_RTCSEL"
+#endif
+
+#endif /* !STM32_LSE_ENABLED */
+
+/**
+ * @brief STM32_PLLM field.
+ */
+#if ((STM32_PLLM_VALUE >= 2) && (STM32_PLLM_VALUE <= 63)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLM (STM32_PLLM_VALUE << 0)
+#else
+#error "invalid STM32_PLLM_VALUE value specified"
+#endif
+
+/**
+ * @brief PLLs input clock frequency.
+ */
+#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__)
+#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE)
+#elif STM32_PLLSRC == STM32_PLLSRC_HSI
+#define STM32_PLLCLKIN (STM32_HSICLK / STM32_PLLM_VALUE)
+#else
+#error "invalid STM32_PLLSRC value specified"
+#endif
+
+/*
+ * PLLs input frequency range check.
+ */
+#if (STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX)
+#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)"
+#endif
+
+/*
+ * PLL enable check.
+ */
+#if STM32_CLOCK48_REQUIRED || \
+ (STM32_SW == STM32_SW_PLL) || \
+ (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \
+ (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL activation flag.
+ */
+#define STM32_ACTIVATE_PLL TRUE
+#else
+#define STM32_ACTIVATE_PLL FALSE
+#endif
+
+/**
+ * @brief STM32_PLLN field.
+ */
+#if ((STM32_PLLN_VALUE >= 64) && (STM32_PLLN_VALUE <= 432)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLN (STM32_PLLN_VALUE << 6)
+#else
+#error "invalid STM32_PLLN_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLP field.
+ */
+#if (STM32_PLLP_VALUE == 2) || defined(__DOXYGEN__)
+#define STM32_PLLP (0 << 16)
+#elif STM32_PLLP_VALUE == 4
+#define STM32_PLLP (1 << 16)
+#elif STM32_PLLP_VALUE == 6
+#define STM32_PLLP (2 << 16)
+#elif STM32_PLLP_VALUE == 8
+#define STM32_PLLP (3 << 16)
+#else
+#error "invalid STM32_PLLP_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLQ field.
+ */
+#if ((STM32_PLLQ_VALUE >= 2) && (STM32_PLLQ_VALUE <= 15)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLQ (STM32_PLLQ_VALUE << 24)
+#else
+#error "invalid STM32_PLLQ_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL VCO frequency.
+ */
+#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE)
+
+/*
+ * PLL VCO frequency range check.
+ */
+#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)
+#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)"
+#endif
+
+/**
+ * @brief PLL output clock frequency.
+ */
+#define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE)
+
+/*
+ * PLL output frequency range check.
+ */
+#if (STM32_PLLCLKOUT < STM32_PLLOUT_MIN) || (STM32_PLLCLKOUT > STM32_PLLOUT_MAX)
+#error "STM32_PLLCLKOUT outside acceptable range (STM32_PLLOUT_MIN...STM32_PLLOUT_MAX)"
+#endif
+
+/**
+ * @brief System clock source.
+ */
+#if STM32_NO_INIT || defined(__DOXYGEN__)
+#define STM32_SYSCLK STM32_HSICLK
+#elif (STM32_SW == STM32_SW_HSI)
+#define STM32_SYSCLK STM32_HSICLK
+#elif (STM32_SW == STM32_SW_HSE)
+#define STM32_SYSCLK STM32_HSECLK
+#elif (STM32_SW == STM32_SW_PLL)
+#define STM32_SYSCLK STM32_PLLCLKOUT
+#else
+#error "invalid STM32_SW value specified"
+#endif
+
+/* Check on the system clock.*/
+#if STM32_SYSCLK > STM32_SYSCLK_MAX
+#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)"
+#endif
+
+/* Calculating VOS settings, it is different for each sub-platform.*/
+#if defined(STM32F429_439xx) || defined(STM32F427_437xx) || \
+ defined(__DOXYGEN__)
+#if STM32_SYSCLK <= 120000000
+#define STM32_VOS STM32_VOS_SCALE3
+#define STM32_OVERDRIVE_REQUIRED FALSE
+#elif STM32_SYSCLK <= 144000000
+#define STM32_VOS STM32_VOS_SCALE2
+#define STM32_OVERDRIVE_REQUIRED FALSE
+#elif STM32_SYSCLK <= 168000000
+#define STM32_VOS STM32_VOS_SCALE1
+#define STM32_OVERDRIVE_REQUIRED FALSE
+#else
+#define STM32_VOS STM32_VOS_SCALE1
+#define STM32_OVERDRIVE_REQUIRED TRUE
+#endif
+
+#elif defined(STM32F40_41xxx)
+#if STM32_SYSCLK <= 144000000
+#define STM32_VOS STM32_VOS_SCALE2
+#else
+#define STM32_VOS STM32_VOS_SCALE1
+#endif
+#define STM32_OVERDRIVE_REQUIRED FALSE
+
+#elif defined(STM32F401xx)
+#if STM32_SYSCLK <= 60000000
+#define STM32_VOS STM32_VOS_SCALE3
+#else
+#define STM32_VOS STM32_VOS_SCALE2
+#endif
+#define STM32_OVERDRIVE_REQUIRED FALSE
+
+#else /* STM32F2XX */
+#define STM32_OVERDRIVE_REQUIRED FALSE
+#endif
+
+/**
+ * @brief AHB frequency.
+ */
+#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__)
+#define STM32_HCLK (STM32_SYSCLK / 1)
+#elif STM32_HPRE == STM32_HPRE_DIV2
+#define STM32_HCLK (STM32_SYSCLK / 2)
+#elif STM32_HPRE == STM32_HPRE_DIV4
+#define STM32_HCLK (STM32_SYSCLK / 4)
+#elif STM32_HPRE == STM32_HPRE_DIV8
+#define STM32_HCLK (STM32_SYSCLK / 8)
+#elif STM32_HPRE == STM32_HPRE_DIV16
+#define STM32_HCLK (STM32_SYSCLK / 16)
+#elif STM32_HPRE == STM32_HPRE_DIV64
+#define STM32_HCLK (STM32_SYSCLK / 64)
+#elif STM32_HPRE == STM32_HPRE_DIV128
+#define STM32_HCLK (STM32_SYSCLK / 128)
+#elif STM32_HPRE == STM32_HPRE_DIV256
+#define STM32_HCLK (STM32_SYSCLK / 256)
+#elif STM32_HPRE == STM32_HPRE_DIV512
+#define STM32_HCLK (STM32_SYSCLK / 512)
+#else
+#error "invalid STM32_HPRE value specified"
+#endif
+
+/*
+ * AHB frequency check.
+ */
+#if STM32_HCLK > STM32_SYSCLK_MAX
+#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)"
+#endif
+
+/**
+ * @brief APB1 frequency.
+ */
+#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK1 (STM32_HCLK / 1)
+#elif STM32_PPRE1 == STM32_PPRE1_DIV2
+#define STM32_PCLK1 (STM32_HCLK / 2)
+#elif STM32_PPRE1 == STM32_PPRE1_DIV4
+#define STM32_PCLK1 (STM32_HCLK / 4)
+#elif STM32_PPRE1 == STM32_PPRE1_DIV8
+#define STM32_PCLK1 (STM32_HCLK / 8)
+#elif STM32_PPRE1 == STM32_PPRE1_DIV16
+#define STM32_PCLK1 (STM32_HCLK / 16)
+#else
+#error "invalid STM32_PPRE1 value specified"
+#endif
+
+/*
+ * APB1 frequency check.
+ */
+#if STM32_PCLK1 > STM32_PCLK1_MAX
+#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)"
+#endif
+
+/**
+ * @brief APB2 frequency.
+ */
+#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK2 (STM32_HCLK / 1)
+#elif STM32_PPRE2 == STM32_PPRE2_DIV2
+#define STM32_PCLK2 (STM32_HCLK / 2)
+#elif STM32_PPRE2 == STM32_PPRE2_DIV4
+#define STM32_PCLK2 (STM32_HCLK / 4)
+#elif STM32_PPRE2 == STM32_PPRE2_DIV8
+#define STM32_PCLK2 (STM32_HCLK / 8)
+#elif STM32_PPRE2 == STM32_PPRE2_DIV16
+#define STM32_PCLK2 (STM32_HCLK / 16)
+#else
+#error "invalid STM32_PPRE2 value specified"
+#endif
+
+/*
+ * APB2 frequency check.
+ */
+#if STM32_PCLK2 > STM32_PCLK2_MAX
+#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)"
+#endif
+
+/*
+ * PLLI2S enable check.
+ */
+#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || defined(__DOXYGEN__)
+/**
+ * @brief PLL activation flag.
+ */
+#define STM32_ACTIVATE_PLLI2S TRUE
+#else
+#define STM32_ACTIVATE_PLLI2S FALSE
+#endif
+
+/**
+ * @brief STM32_PLLI2SN field.
+ */
+#if ((STM32_PLLI2SN_VALUE >= 192) && (STM32_PLLI2SN_VALUE <= 432)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6)
+#else
+#error "invalid STM32_PLLI2SN_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLI2SR field.
+ */
+#if ((STM32_PLLI2SR_VALUE >= 2) && (STM32_PLLI2SR_VALUE <= 7)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLI2SR (STM32_PLLI2SR_VALUE << 28)
+#else
+#error "invalid STM32_PLLI2SR_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL VCO frequency.
+ */
+#define STM32_PLLI2SVCO (STM32_PLLCLKIN * STM32_PLLI2SN_VALUE)
+
+/*
+ * PLLI2S VCO frequency range check.
+ */
+#if (STM32_PLLI2SVCO < STM32_PLLVCO_MIN) || \
+ (STM32_PLLI2SVCO > STM32_PLLVCO_MAX)
+#error "STM32_PLLI2SVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)"
+#endif
+
+/**
+ * @brief PLLI2S output clock frequency.
+ */
+#define STM32_PLLI2SCLKOUT (STM32_PLLI2SVCO / STM32_PLLI2SR_VALUE)
+
+/**
+ * @brief MCO1 divider clock.
+ */
+#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || defined(__DOXYGEN__)
+#define STM32_MCO1DIVCLK STM32_HSICLK
+#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE
+#define STM32_MCO1DIVCLK STM32_LSECLK
+#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE
+#define STM32_MCO1DIVCLK STM32_HSECLK
+#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL
+#define STM32_MCO1DIVCLK STM32_PLLCLKOUT
+#else
+#error "invalid STM32_MCO1SEL value specified"
+#endif
+
+/**
+ * @brief MCO1 output pin clock.
+ */
+#if (STM32_MCO1PRE == STM32_MCO1PRE_DIV1) || defined(__DOXYGEN__)
+#define STM32_MCO1CLK STM32_MCO1DIVCLK
+#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV2
+#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 2)
+#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV3
+#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 3)
+#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV4
+#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 4)
+#elif STM32_MCO1PRE == STM32_MCO1PRE_DIV5
+#define STM32_MCO1CLK (STM32_MCO1DIVCLK / 5)
+#else
+#error "invalid STM32_MCO1PRE value specified"
+#endif
+
+/**
+ * @brief MCO2 divider clock.
+ */
+#if (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || defined(__DOXYGEN__)
+#define STM32_MCO2DIVCLK STM32_HSECLK
+#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL
+#define STM32_MCO2DIVCLK STM32_PLLCLKOUT
+#elif STM32_MCO2SEL == STM32_MCO2SEL_SYSCLK
+#define STM32_MCO2DIVCLK STM32_SYSCLK
+#elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S
+#define STM32_MCO2DIVCLK STM32_PLLI2S
+#else
+#error "invalid STM32_MCO2SEL value specified"
+#endif
+
+/**
+ * @brief MCO2 output pin clock.
+ */
+#if (STM32_MCO2PRE == STM32_MCO2PRE_DIV1) || defined(__DOXYGEN__)
+#define STM32_MCO2CLK STM32_MCO2DIVCLK
+#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV2
+#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 2)
+#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV3
+#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 3)
+#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV4
+#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 4)
+#elif STM32_MCO2PRE == STM32_MCO2PRE_DIV5
+#define STM32_MCO2CLK (STM32_MCO2DIVCLK / 5)
+#else
+#error "invalid STM32_MCO2PRE value specified"
+#endif
+
+/**
+ * @brief RTC HSE divider setting.
+ */
+#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \
+ defined(__DOXYGEN__)
+#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16)
+#else
+#error "invalid STM32_RTCPRE value specified"
+#endif
+
+/**
+ * @brief HSE divider toward RTC clock.
+ */
+#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \
+ defined(__DOXYGEN__)
+#define STM32_HSEDIVCLK (STM32_HSECLK / STM32_RTCPRE_VALUE)
+#else
+#error "invalid STM32_RTCPRE value specified"
+#endif
+
+/**
+ * @brief RTC clock.
+ */
+#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__)
+#define STM32_RTCCLK 0
+#elif STM32_RTCSEL == STM32_RTCSEL_LSE
+#define STM32_RTCCLK STM32_LSECLK
+#elif STM32_RTCSEL == STM32_RTCSEL_LSI
+#define STM32_RTCCLK STM32_LSICLK
+#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV
+#define STM32_RTCCLK STM32_HSEDIVCLK
+#else
+#error "invalid STM32_RTCSEL value specified"
+#endif
+
+/**
+ * @brief 48MHz frequency.
+ */
+#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__)
+#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE)
+#else
+#define STM32_PLL48CLK 0
+#endif
+
+/**
+ * @brief Timers 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14 clock.
+ */
+#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__)
+#define STM32_TIMCLK1 (STM32_PCLK1 * 1)
+#else
+#define STM32_TIMCLK1 (STM32_PCLK1 * 2)
+#endif
+
+/**
+ * @brief Timers 1, 8 clock.
+ */
+#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__)
+#define STM32_TIMCLK2 (STM32_PCLK2 * 1)
+#else
+#define STM32_TIMCLK2 (STM32_PCLK2 * 2)
+#endif
+
+/**
+ * @brief Flash settings.
+ */
+#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_FLASHBITS 0x00000000
+#elif STM32_HCLK <= STM32_1WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000001
+#elif STM32_HCLK <= STM32_2WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000002
+#elif STM32_HCLK <= STM32_3WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000003
+#elif STM32_HCLK <= STM32_4WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000004
+#elif STM32_HCLK <= STM32_5WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000005
+#elif STM32_HCLK <= STM32_6WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000006
+#elif STM32_HCLK <= STM32_7WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000007
+#else
+#define STM32_FLASHBITS 0x00000008
+#endif
+
+/* There are differences in vector names in the various sub-families,
+ normalizing.*/
+#if 0
+#define TIM1_BRK_IRQn TIM1_BRK_TIM9_IRQn
+#define TIM1_UP_IRQn TIM1_UP_TIM10_IRQn
+#define TIM1_TRG_COM_IRQn TIM1_TRG_COM_TIM11_IRQn
+#define TIM8_BRK_IRQn TIM8_BRK_TIM12_IRQn
+#define TIM8_UP_IRQn TIM8_UP_TIM13_IRQn
+#define TIM8_TRG_COM_IRQn TIM8_TRG_COM_TIM14_IRQn
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* Various helpers.*/
+#include "nvic.h"
+#include "stm32_isr.h"
+#include "stm32_dma.h"
+#include "stm32_rcc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+ void stm32_clock_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/platform.mk b/os/hal/ports/STM32/STM32F4xx/platform.mk
new file mode 100644
index 000000000..d91d96409
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/platform.mk
@@ -0,0 +1,33 @@
+# List of all the STM32F2xx/STM32F4xx platform files.
+PLATFORMSRC = ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \
+ ${CHIBIOS}/os/hal/ports/STM32F4xx/stm32_dma.c \
+ ${CHIBIOS}/os/hal/ports/STM32F4xx/hal_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32F4xx/adc_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32F4xx/ext_lld_isr.c \
+ ${CHIBIOS}/os/hal/ports/STM32/can_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/ext_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/mac_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/sdc_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/GPIOv2/pal_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/I2Cv1/i2c_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/OTGv1/usb_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/RTCv2/rtc_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/SPIv1/spi_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/TIMv1/gpt_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/TIMv1/icu_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/TIMv1/pwm_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/TIMv1/st_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/USARTv1/serial_lld.c \
+ ${CHIBIOS}/os/hal/ports/STM32/USARTv1/uart_lld.c
+
+# Required include directories
+PLATFORMINC = ${CHIBIOS}/os/hal/ports/common/ARMCMx \
+ ${CHIBIOS}/os/hal/ports/STM32F4xx \
+ ${CHIBIOS}/os/hal/ports/STM32 \
+ ${CHIBIOS}/os/hal/ports/STM32/GPIOv2 \
+ ${CHIBIOS}/os/hal/ports/STM32/I2Cv1 \
+ ${CHIBIOS}/os/hal/ports/STM32/OTGv1 \
+ ${CHIBIOS}/os/hal/ports/STM32/RTCv2 \
+ ${CHIBIOS}/os/hal/ports/STM32/SPIv1 \
+ ${CHIBIOS}/os/hal/ports/STM32/TIMv1 \
+ ${CHIBIOS}/os/hal/ports/STM32/USARTv1
diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_dma.c b/os/hal/ports/STM32/STM32F4xx/stm32_dma.c
new file mode 100644
index 000000000..f64e34b4f
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/stm32_dma.c
@@ -0,0 +1,527 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/stm32_dma.c
+ * @brief Enhanced DMA helper driver code.
+ *
+ * @addtogroup STM32F4xx_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 "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 0x000000FF
+
+/**
+ * @brief Mask of the DMA2 streams in @p dma_streams_mask.
+ */
+#define STM32_DMA2_STREAMS_MASK 0x0000FF00
+
+/**
+ * @brief Post-reset value of the stream CR register.
+ */
+#define STM32_DMA_CR_RESET_VALUE 0x00000000
+
+/**
+ * @brief Post-reset value of the stream FCR register.
+ */
+#define STM32_DMA_FCR_RESET_VALUE 0x00000021
+
+/*===========================================================================*/
+/* 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_STREAM0, @p STM32_DMA1_STREAM1 etc.
+ */
+const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
+ {DMA1_Stream0, &DMA1->LIFCR, 0, 0, DMA1_Stream0_IRQn},
+ {DMA1_Stream1, &DMA1->LIFCR, 6, 1, DMA1_Stream1_IRQn},
+ {DMA1_Stream2, &DMA1->LIFCR, 16, 2, DMA1_Stream2_IRQn},
+ {DMA1_Stream3, &DMA1->LIFCR, 22, 3, DMA1_Stream3_IRQn},
+ {DMA1_Stream4, &DMA1->HIFCR, 0, 4, DMA1_Stream4_IRQn},
+ {DMA1_Stream5, &DMA1->HIFCR, 6, 5, DMA1_Stream5_IRQn},
+ {DMA1_Stream6, &DMA1->HIFCR, 16, 6, DMA1_Stream6_IRQn},
+ {DMA1_Stream7, &DMA1->HIFCR, 22, 7, DMA1_Stream7_IRQn},
+ {DMA2_Stream0, &DMA2->LIFCR, 0, 8, DMA2_Stream0_IRQn},
+ {DMA2_Stream1, &DMA2->LIFCR, 6, 9, DMA2_Stream1_IRQn},
+ {DMA2_Stream2, &DMA2->LIFCR, 16, 10, DMA2_Stream2_IRQn},
+ {DMA2_Stream3, &DMA2->LIFCR, 22, 11, DMA2_Stream3_IRQn},
+ {DMA2_Stream4, &DMA2->HIFCR, 0, 12, DMA2_Stream4_IRQn},
+ {DMA2_Stream5, &DMA2->HIFCR, 6, 13, DMA2_Stream5_IRQn},
+ {DMA2_Stream6, &DMA2->HIFCR, 16, 14, DMA2_Stream6_IRQn},
+ {DMA2_Stream7, &DMA2->HIFCR, 22, 15, DMA2_Stream7_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 0 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector6C) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 0) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 0;
+ if (dma_isr_redir[0].dma_func)
+ dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 1 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector70) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 6) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 6;
+ if (dma_isr_redir[1].dma_func)
+ dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 2 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector74) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 16) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 16;
+ if (dma_isr_redir[2].dma_func)
+ dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 3 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector78) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 22) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 22;
+ if (dma_isr_redir[3].dma_func)
+ dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 4 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector7C) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 0) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 0;
+ if (dma_isr_redir[4].dma_func)
+ dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 5 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector80) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 6) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 6;
+ if (dma_isr_redir[5].dma_func)
+ dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 6 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector84) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 16) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 16;
+ if (dma_isr_redir[6].dma_func)
+ dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 7 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(VectorFC) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 22) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 22;
+ if (dma_isr_redir[7].dma_func)
+ dma_isr_redir[7].dma_func(dma_isr_redir[7].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 0 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector120) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 0) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 0;
+ if (dma_isr_redir[8].dma_func)
+ dma_isr_redir[8].dma_func(dma_isr_redir[8].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 1 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector124) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 6) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 6;
+ if (dma_isr_redir[9].dma_func)
+ dma_isr_redir[9].dma_func(dma_isr_redir[9].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 2 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector128) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 16) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 16;
+ if (dma_isr_redir[10].dma_func)
+ dma_isr_redir[10].dma_func(dma_isr_redir[10].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 3 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector12C) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 22) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 22;
+ if (dma_isr_redir[11].dma_func)
+ dma_isr_redir[11].dma_func(dma_isr_redir[11].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 4 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector130) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 0) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 0;
+ if (dma_isr_redir[12].dma_func)
+ dma_isr_redir[12].dma_func(dma_isr_redir[12].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 5 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector150) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 6) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 6;
+ if (dma_isr_redir[13].dma_func)
+ dma_isr_redir[13].dma_func(dma_isr_redir[13].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 6 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector154) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 16) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 16;
+ if (dma_isr_redir[14].dma_func)
+ dma_isr_redir[14].dma_func(dma_isr_redir[14].dma_param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 7 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(Vector158) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 22) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 22;
+ if (dma_isr_redir[15].dma_func)
+ dma_isr_redir[15].dma_func(dma_isr_redir[15].dma_param, flags);
+
+ OSAL_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].stream->CR = 0;
+ dma_isr_redir[i].dma_func = NULL;
+ }
+ DMA1->LIFCR = 0xFFFFFFFF;
+ DMA1->HIFCR = 0xFFFFFFFF;
+ DMA2->LIFCR = 0xFFFFFFFF;
+ DMA2->HIFCR = 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 dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param) {
+
+ osalDbgCheck(dmastp != NULL);
+
+ /* 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);
+ if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0)
+ rccEnableDMA2(FALSE);
+
+ /* Putting the stream in a safe state.*/
+ dmaStreamDisable(dmastp);
+ dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE;
+ dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE;
+
+ /* Enables the associated IRQ vector if a callback is defined.*/
+ if (func != NULL)
+ nvicEnableVector(dmastp->vector, 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) {
+
+ osalDbgCheck(dmastp != NULL);
+
+ /* Check if the streams is not taken.*/
+ osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0,
+ "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);
+ if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0)
+ rccDisableDMA2(FALSE);
+}
+
+#endif /* STM32_DMA_REQUIRED */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_dma.h b/os/hal/ports/STM32/STM32F4xx/stm32_dma.h
new file mode 100644
index 000000000..cb0d01688
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/stm32_dma.h
@@ -0,0 +1,461 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/stm32_dma.h
+ * @brief Enhanced-DMA helper driver header.
+ * @note This file requires definitions from the ST STM32F4xx header file
+ * stm32f4xx.h.
+ *
+ * @addtogroup STM32F4xx_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 16
+
+/**
+ * @brief Mask of the ISR bits passed to the DMA callback functions.
+ */
+#define STM32_DMA_ISR_MASK 0x3D
+
+/**
+ * @brief Returns the channel associated to the specified stream.
+ *
+ * @param[in] id the unique numeric stream identifier
+ * @param[in] c a stream/channel association word, one channel per
+ * nibble
+ * @return Returns the channel associated to the stream.
+ */
+#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
+ * @param[in] stream the stream number
+ * @return An unique numeric stream identifier.
+ */
+#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 8) + (stream))
+
+/**
+ * @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_STREAM0 STM32_DMA_STREAM(0)
+#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(1)
+#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(2)
+#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(3)
+#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(4)
+#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(5)
+#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(6)
+#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(7)
+#define STM32_DMA2_STREAM0 STM32_DMA_STREAM(8)
+#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(9)
+#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(10)
+#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(11)
+#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(12)
+#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(13)
+#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(14)
+#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(15)
+/** @} */
+
+/**
+ * @name CR register constants common to all DMA types
+ * @{
+ */
+#define STM32_DMA_CR_EN DMA_SxCR_EN
+#define STM32_DMA_CR_TEIE DMA_SxCR_TEIE
+#define STM32_DMA_CR_HTIE DMA_SxCR_HTIE
+#define STM32_DMA_CR_TCIE DMA_SxCR_TCIE
+#define STM32_DMA_CR_DIR_MASK DMA_SxCR_DIR
+#define STM32_DMA_CR_DIR_P2M 0
+#define STM32_DMA_CR_DIR_M2P DMA_SxCR_DIR_0
+#define STM32_DMA_CR_DIR_M2M DMA_SxCR_DIR_1
+#define STM32_DMA_CR_CIRC DMA_SxCR_CIRC
+#define STM32_DMA_CR_PINC DMA_SxCR_PINC
+#define STM32_DMA_CR_MINC DMA_SxCR_MINC
+#define STM32_DMA_CR_PSIZE_MASK DMA_SxCR_PSIZE
+#define STM32_DMA_CR_PSIZE_BYTE 0
+#define STM32_DMA_CR_PSIZE_HWORD DMA_SxCR_PSIZE_0
+#define STM32_DMA_CR_PSIZE_WORD DMA_SxCR_PSIZE_1
+#define STM32_DMA_CR_MSIZE_MASK DMA_SxCR_MSIZE
+#define STM32_DMA_CR_MSIZE_BYTE 0
+#define STM32_DMA_CR_MSIZE_HWORD DMA_SxCR_MSIZE_0
+#define STM32_DMA_CR_MSIZE_WORD DMA_SxCR_MSIZE_1
+#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \
+ STM32_DMA_CR_MSIZE_MASK)
+#define STM32_DMA_CR_PL_MASK DMA_SxCR_PL
+#define STM32_DMA_CR_PL(n) ((n) << 16)
+/** @} */
+
+/**
+ * @name CR register constants only found in STM32F2xx/STM32F4xx
+ * @{
+ */
+#define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE
+#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL
+#define STM32_DMA_CR_PINCOS DMA_SxCR_PINCOS
+#define STM32_DMA_CR_DBM DMA_SxCR_DBM
+#define STM32_DMA_CR_CT DMA_SxCR_CT
+#define STM32_DMA_CR_PBURST_MASK DMA_SxCR_PBURST
+#define STM32_DMA_CR_PBURST_SINGLE 0
+#define STM32_DMA_CR_PBURST_INCR4 DMA_SxCR_PBURST_0
+#define STM32_DMA_CR_PBURST_INCR8 DMA_SxCR_PBURST_1
+#define STM32_DMA_CR_PBURST_INCR16 (DMA_SxCR_PBURST_0 | DMA_SxCR_PBURST_1)
+#define STM32_DMA_CR_MBURST_MASK DMA_SxCR_MBURST
+#define STM32_DMA_CR_MBURST_SINGLE 0
+#define STM32_DMA_CR_MBURST_INCR4 DMA_SxCR_MBURST_0
+#define STM32_DMA_CR_MBURST_INCR8 DMA_SxCR_MBURST_1
+#define STM32_DMA_CR_MBURST_INCR16 (DMA_SxCR_MBURST_0 | DMA_SxCR_MBURST_1)
+#define STM32_DMA_CR_CHSEL_MASK DMA_SxCR_CHSEL
+#define STM32_DMA_CR_CHSEL(n) ((n) << 25)
+/** @} */
+
+/**
+ * @name FCR register constants only found in STM32F2xx/STM32F4xx
+ * @{
+ */
+#define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE
+#define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS
+#define STM32_DMA_FCR_DMDIS DMA_SxFCR_DMDIS
+#define STM32_DMA_FCR_FTH_MASK DMA_SxFCR_FTH
+#define STM32_DMA_FCR_FTH_1Q 0
+#define STM32_DMA_FCR_FTH_HALF DMA_SxFCR_FTH_0
+#define STM32_DMA_FCR_FTH_3Q DMA_SxFCR_FTH_1
+#define STM32_DMA_FCR_FTH_FULL (DMA_SxFCR_FTH_0 | DMA_SxFCR_FTH_1)
+/** @} */
+
+/**
+ * @name Status flags passed to the ISR callbacks
+ */
+#define STM32_DMA_ISR_FEIF DMA_LISR_FEIF0
+#define STM32_DMA_ISR_DMEIF DMA_LISR_DMEIF0
+#define STM32_DMA_ISR_TEIF DMA_LISR_TEIF0
+#define STM32_DMA_ISR_HTIF DMA_LISR_HTIF0
+#define STM32_DMA_ISR_TCIF DMA_LISR_TCIF0
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA stream descriptor structure.
+ */
+typedef struct {
+ DMA_Stream_TypeDef *stream; /**< @brief Associated DMA stream. */
+ 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 xISR 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 PAR register
+ *
+ * @special
+ */
+#define dmaStreamSetPeripheral(dmastp, addr) { \
+ (dmastp)->stream->PAR = (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 M0AR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory0(dmastp, addr) { \
+ (dmastp)->stream->M0AR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates an alternate memory destination to a DMA stream.
+ * @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] addr value to be written in the M1AR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory1(dmastp, addr) { \
+ (dmastp)->stream->M1AR = (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)->stream->NDTR = (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)->stream->NDTR))
+
+/**
+ * @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 CR register
+ *
+ * @special
+ */
+#define dmaStreamSetMode(dmastp, mode) { \
+ (dmastp)->stream->CR = (uint32_t)(mode); \
+}
+
+/**
+ * @brief Programs the stream FIFO 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 FCR register
+ *
+ * @special
+ */
+#define dmaStreamSetFIFO(dmastp, mode) { \
+ (dmastp)->stream->FCR = (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)->stream->CR |= STM32_DMA_CR_EN; \
+}
+
+/**
+ * @brief DMA stream disable.
+ * @details The function disables the specified stream, waits for the disable
+ * operation to complete and then clears any pending interrupt.
+ * @note This function can be invoked in both ISR or thread context.
+ * @note Interrupts enabling flags are set to zero after this call, see
+ * bug 3607518.
+ * @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)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE | \
+ STM32_DMA_CR_EN); \
+ while (((dmastp)->stream->CR & STM32_DMA_CR_EN) != 0) \
+ ; \
+ 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)->stream->NDTR > 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 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/ports/STM32/STM32F4xx/stm32_isr.h b/os/hal/ports/STM32/STM32F4xx/stm32_isr.h
new file mode 100644
index 000000000..0e936b3d6
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/stm32_isr.h
@@ -0,0 +1,150 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/stm32_isr.h
+ * @brief ISR remapper driver header.
+ *
+ * @addtogroup STM32F4xx_ISR
+ * @{
+ */
+
+#ifndef _STM32_ISR_H_
+#define _STM32_ISR_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name ISR names and numbers remapping
+ * @{
+ */
+/*
+ * CAN units.
+ */
+#define STM32_CAN1_TX_HANDLER Vector8C
+#define STM32_CAN1_RX0_HANDLER Vector90
+#define STM32_CAN1_RX1_HANDLER Vector94
+#define STM32_CAN1_SCE_HANDLER Vector98
+#define STM32_CAN2_TX_HANDLER Vector13C
+#define STM32_CAN2_RX0_HANDLER Vector140
+#define STM32_CAN2_RX1_HANDLER Vector144
+#define STM32_CAN2_SCE_HANDLER Vector148
+
+#define STM32_CAN1_TX_NUMBER 19
+#define STM32_CAN1_RX0_NUMBER 20
+#define STM32_CAN1_RX1_NUMBER 21
+#define STM32_CAN1_SCE_NUMBER 22
+#define STM32_CAN2_TX_NUMBER 63
+#define STM32_CAN2_RX0_NUMBER 64
+#define STM32_CAN2_RX1_NUMBER 65
+#define STM32_CAN2_SCE_NUMBER 66
+
+/*
+ * OTG units.
+ */
+#define STM32_OTG1_HANDLER Vector14C
+#define STM32_OTG2_HANDLER Vector174
+#define STM32_OTG2_EP1OUT_HANDLER Vector168
+#define STM32_OTG2_EP1IN_HANDLER Vector16C
+
+#define STM32_OTG1_NUMBER 67
+#define STM32_OTG2_NUMBER 77
+#define STM32_OTG2_EP1OUT_NUMBER 74
+#define STM32_OTG2_EP1IN_NUMBER 75
+
+/*
+ * SDIO unit.
+ */
+#define STM32_SDIO_HANDLER Vector104
+
+#define STM32_SDIO_NUMBER 49
+
+/*
+ * TIM units.
+ */
+#define STM32_TIM1_UP_HANDLER VectorA4
+#define STM32_TIM1_CC_HANDLER VectorAC
+#define STM32_TIM2_HANDLER VectorB0
+#define STM32_TIM3_HANDLER VectorB4
+#define STM32_TIM4_HANDLER VectorB8
+#define STM32_TIM5_HANDLER Vector108
+#define STM32_TIM6_HANDLER Vector118
+#define STM32_TIM7_HANDLER Vector11C
+#define STM32_TIM8_UP_HANDLER VectorF0
+#define STM32_TIM8_CC_HANDLER VectorF8
+#define STM32_TIM9_HANDLER VectorA0
+#define STM32_TIM11_HANDLER VectorA8
+#define STM32_TIM12_HANDLER VectorEC
+#define STM32_TIM14_HANDLER VectorF4
+
+#define STM32_TIM1_UP_NUMBER 25
+#define STM32_TIM1_CC_NUMBER 27
+#define STM32_TIM2_NUMBER 28
+#define STM32_TIM3_NUMBER 29
+#define STM32_TIM4_NUMBER 30
+#define STM32_TIM5_NUMBER 50
+#define STM32_TIM6_NUMBER 54
+#define STM32_TIM7_NUMBER 55
+#define STM32_TIM8_UP_NUMBER 44
+#define STM32_TIM8_CC_NUMBER 46
+#define STM32_TIM9_NUMBER 24
+#define STM32_TIM11_NUMBER 26
+#define STM32_TIM12_NUMBER 43
+#define STM32_TIM14_NUMBER 45
+
+/*
+ * USART units.
+ */
+#define STM32_USART1_HANDLER VectorD4
+#define STM32_USART2_HANDLER VectorD8
+#define STM32_USART3_HANDLER VectorDC
+#define STM32_UART4_HANDLER Vector110
+#define STM32_UART5_HANDLER Vector114
+#define STM32_USART6_HANDLER Vector15C
+
+#define STM32_USART1_NUMBER 37
+#define STM32_USART2_NUMBER 38
+#define STM32_USART3_NUMBER 39
+#define STM32_UART4_NUMBER 52
+#define STM32_UART5_NUMBER 53
+#define STM32_USART6_NUMBER 71
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#endif /* _STM32_ISR_H_ */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_rcc.h b/os/hal/ports/STM32/STM32F4xx/stm32_rcc.h
new file mode 100644
index 000000000..9178f67da
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/stm32_rcc.h
@@ -0,0 +1,1382 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/stm32_rcc.h
+ * @brief RCC helper driver header.
+ * @note This file requires definitions from the ST header file
+ * @p stm32f4xx.h.
+ *
+ * @addtogroup STM32F4xx_RCC
+ * @{
+ */
+#ifndef _STM32_RCC_
+#define _STM32_RCC_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Generic RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB1(mask, lp) { \
+ RCC->APB1ENR |= (mask); \
+ if (lp) \
+ RCC->APB1LPENR |= (mask); \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableAPB1(mask, lp) { \
+ RCC->APB1ENR &= ~(mask); \
+ if (lp) \
+ RCC->APB1LPENR &= ~(mask); \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB1(mask) { \
+ RCC->APB1RSTR |= (mask); \
+ RCC->APB1RSTR = 0; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB2(mask, lp) { \
+ RCC->APB2ENR |= (mask); \
+ if (lp) \
+ RCC->APB2LPENR |= (mask); \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableAPB2(mask, lp) { \
+ RCC->APB2ENR &= ~(mask); \
+ if (lp) \
+ RCC->APB2LPENR &= ~(mask); \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB2(mask) { \
+ RCC->APB2RSTR |= (mask); \
+ RCC->APB2RSTR = 0; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB1(mask, lp) { \
+ RCC->AHB1ENR |= (mask); \
+ if (lp) \
+ RCC->AHB1LPENR |= (mask); \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableAHB1(mask, lp) { \
+ RCC->AHB1ENR &= ~(mask); \
+ if (lp) \
+ RCC->AHB1LPENR &= ~(mask); \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB1(mask) { \
+ RCC->AHB1RSTR |= (mask); \
+ RCC->AHB1RSTR = 0; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB2(mask, lp) { \
+ RCC->AHB2ENR |= (mask); \
+ if (lp) \
+ RCC->AHB2LPENR |= (mask); \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableAHB2(mask, lp) { \
+ RCC->AHB2ENR &= ~(mask); \
+ if (lp) \
+ RCC->AHB2LPENR &= ~(mask); \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB2(mask) { \
+ RCC->AHB2RSTR |= (mask); \
+ RCC->AHB2RSTR = 0; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB3(mask, lp) { \
+ RCC->AHB3ENR |= (mask); \
+ if (lp) \
+ RCC->AHB3LPENR |= (mask); \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableAHB3(mask, lp) { \
+ RCC->AHB3ENR &= ~(mask); \
+ if (lp) \
+ RCC->AHB3LPENR &= ~(mask); \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB3(mask) { \
+ RCC->AHB3RSTR |= (mask); \
+ RCC->AHB3RSTR = 0; \
+}
+/** @} */
+
+/**
+ * @name ADC peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the ADC1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp)
+
+/**
+ * @brief Disables the ADC1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableADC1(lp) rccDisableAPB2(RCC_APB2ENR_ADC1EN, lp)
+
+/**
+ * @brief Resets the ADC1 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST)
+
+/**
+ * @brief Enables the ADC2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC2(lp) rccEnableAPB2(RCC_APB2ENR_ADC2EN, lp)
+
+/**
+ * @brief Disables the ADC2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableADC2(lp) rccDisableAPB2(RCC_APB2ENR_ADC2EN, lp)
+
+/**
+ * @brief Resets the ADC2 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC2() rccResetAPB2(RCC_APB2RSTR_ADC2RST)
+
+/**
+ * @brief Enables the ADC3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC3(lp) rccEnableAPB2(RCC_APB2ENR_ADC3EN, lp)
+
+/**
+ * @brief Disables the ADC3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableADC3(lp) rccDisableAPB2(RCC_APB2ENR_ADC3EN, lp)
+
+/**
+ * @brief Resets the ADC3 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST)
+/** @} */
+
+/**
+ * @name DMA peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp)
+
+/**
+ * @brief Disables the DMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableDMA1(lp) rccDisableAHB1(RCC_AHB1ENR_DMA1EN, lp)
+
+/**
+ * @brief Resets the DMA1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA1() rccResetAHB1(RCC_AHB1RSTR_DMA1RST)
+
+/**
+ * @brief Enables the DMA2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA2(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2EN, lp)
+
+/**
+ * @brief Disables the DMA2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableDMA2(lp) rccDisableAHB1(RCC_AHB1ENR_DMA2EN, lp)
+
+/**
+ * @brief Resets the DMA2 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST)
+/** @} */
+
+/**
+ * @name BKPSRAM specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the BKPSRAM peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableBKPSRAM(lp) rccEnableAHB1(RCC_AHB1ENR_BKPSRAMEN, lp)
+
+/**
+ * @brief Disables the BKPSRAM peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableBKPSRAM(lp) rccDisableAHB1(RCC_AHB1ENR_BKPSRAMEN, lp)
+/** @} */
+
+/**
+ * @name PWR interface specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the PWR interface clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnablePWRInterface(lp) rccEnableAPB1(RCC_APB1ENR_PWREN, lp)
+
+/**
+ * @brief Disables PWR interface clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisablePWRInterface(lp) rccDisableAPB1(RCC_APB1ENR_PWREN, lp)
+
+/**
+ * @brief Resets the PWR interface.
+ *
+ * @api
+ */
+#define rccResetPWRInterface() rccResetAPB1(RCC_APB1RSTR_PWRRST)
+/** @} */
+
+
+/**
+ * @name CAN peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the CAN1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableCAN1(lp) rccEnableAPB1(RCC_APB1ENR_CAN1EN, lp)
+
+/**
+ * @brief Disables the CAN1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableCAN1(lp) rccDisableAPB1(RCC_APB1ENR_CAN1EN, lp)
+
+/**
+ * @brief Resets the CAN1 peripheral.
+ *
+ * @api
+ */
+#define rccResetCAN1() rccResetAPB1(RCC_APB1RSTR_CAN1RST)
+
+/**
+ * @brief Enables the CAN2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableCAN2(lp) rccEnableAPB1(RCC_APB1ENR_CAN2EN, lp)
+
+/**
+ * @brief Disables the CAN2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableCAN2(lp) rccDisableAPB1(RCC_APB1ENR_CAN2EN, lp)
+
+/**
+ * @brief Resets the CAN2 peripheral.
+ *
+ * @api
+ */
+#define rccResetCAN2() rccResetAPB1(RCC_APB1RSTR_CAN2RST)
+/** @} */
+
+/**
+ * @name ETH peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the ETH peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \
+ RCC_AHB1ENR_ETHMACTXEN | \
+ RCC_AHB1ENR_ETHMACRXEN, lp)
+
+/**
+ * @brief Disables the ETH peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableETH(lp) rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \
+ RCC_AHB1ENR_ETHMACTXEN | \
+ RCC_AHB1ENR_ETHMACRXEN, lp)
+
+/**
+ * @brief Resets the ETH peripheral.
+ *
+ * @api
+ */
+#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST)
+/** @} */
+
+/**
+ * @name I2C peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the I2C1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp)
+
+/**
+ * @brief Disables the I2C1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp)
+
+/**
+ * @brief Resets the I2C1 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST)
+
+/**
+ * @brief Enables the I2C2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp)
+
+/**
+ * @brief Disables the I2C2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp)
+
+/**
+ * @brief Resets the I2C2 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST)
+
+/**
+ * @brief Enables the I2C3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C3(lp) rccEnableAPB1(RCC_APB1ENR_I2C3EN, lp)
+
+/**
+ * @brief Disables the I2C3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableI2C3(lp) rccDisableAPB1(RCC_APB1ENR_I2C3EN, lp)
+
+/**
+ * @brief Resets the I2C3 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST)
+/** @} */
+
+/**
+ * @name OTG peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the OTG_FS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp)
+
+/**
+ * @brief Disables the OTG_FS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableOTG_FS(lp) rccDisableAHB2(RCC_AHB2ENR_OTGFSEN, lp)
+
+/**
+ * @brief Resets the OTG_FS peripheral.
+ *
+ * @api
+ */
+#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST)
+
+/**
+ * @brief Enables the OTG_HS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableOTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_OTGHSEN, lp)
+
+/**
+ * @brief Disables the OTG_HS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableOTG_HS(lp) rccDisableAHB1(RCC_AHB1ENR_OTGHSEN, lp)
+
+/**
+ * @brief Resets the OTG_HS peripheral.
+ *
+ * @api
+ */
+#define rccResetOTG_HS() rccResetAHB1(RCC_AHB1RSTR_OTGHSRST)
+/** @} */
+
+/**
+ * @name SDIO peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the SDIO peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSDIO(lp) rccEnableAPB2(RCC_APB2ENR_SDIOEN, lp)
+
+/**
+ * @brief Disables the SDIO peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableSDIO(lp) rccDisableAPB2(RCC_APB2ENR_SDIOEN, lp)
+
+/**
+ * @brief Resets the SDIO peripheral.
+ * @note Not supported in this family, does nothing.
+ *
+ * @api
+ */
+#define rccResetSDIO() rccResetAPB2(RCC_APB2RSTR_SDIORST)
+/** @} */
+
+/**
+ * @name SPI peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the SPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp)
+
+/**
+ * @brief Disables the SPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp)
+
+/**
+ * @brief Resets the SPI1 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST)
+
+/**
+ * @brief Enables the SPI2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp)
+
+/**
+ * @brief Disables the SPI2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp)
+
+/**
+ * @brief Resets the SPI2 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST)
+
+/**
+ * @brief Enables the SPI3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp)
+
+/**
+ * @brief Disables the SPI3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableSPI3(lp) rccDisableAPB1(RCC_APB1ENR_SPI3EN, lp)
+
+/**
+ * @brief Resets the SPI3 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST)
+
+/**
+ * @brief Enables the SPI4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp)
+
+/**
+ * @brief Disables the SPI4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableSPI4(lp) rccDisableAPB2(RCC_APB2ENR_SPI4EN, lp)
+
+/**
+ * @brief Resets the SPI4 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST)
+
+/**
+ * @brief Enables the SPI5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp)
+
+/**
+ * @brief Disables the SPI5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableSPI5(lp) rccDisableAPB2(RCC_APB2ENR_SPI5EN, lp)
+
+/**
+ * @brief Resets the SPI5 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST)
+
+/**
+ * @brief Enables the SPI6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI6(lp) rccEnableAPB2(RCC_APB2ENR_SPI6EN, lp)
+
+/**
+ * @brief Disables the SPI6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableSPI6(lp) rccDisableAPB2(RCC_APB2ENR_SPI6EN, lp)
+
+/**
+ * @brief Resets the SPI6 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI6() rccResetAPB2(RCC_APB2RSTR_SPI6RST)
+/** @} */
+
+/**
+ * @name TIM peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the TIM1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp)
+
+/**
+ * @brief Disables the TIM1 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp)
+
+/**
+ * @brief Resets the TIM1 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST)
+
+/**
+ * @brief Enables the TIM2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp)
+
+/**
+ * @brief Disables the TIM2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp)
+
+/**
+ * @brief Resets the TIM2 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST)
+
+/**
+ * @brief Enables the TIM3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp)
+
+/**
+ * @brief Disables the TIM3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp)
+
+/**
+ * @brief Resets the TIM3 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST)
+
+/**
+ * @brief Enables the TIM4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp)
+
+/**
+ * @brief Disables the TIM4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM4(lp) rccDisableAPB1(RCC_APB1ENR_TIM4EN, lp)
+
+/**
+ * @brief Resets the TIM4 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST)
+
+/**
+ * @brief Enables the TIM5 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp)
+
+/**
+ * @brief Disables the TIM5 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM5(lp) rccDisableAPB1(RCC_APB1ENR_TIM5EN, lp)
+
+/**
+ * @brief Resets the TIM5 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST)
+
+/**
+ * @brief Enables the TIM6 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp)
+
+/**
+ * @brief Disables the TIM6 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM6(lp) rccDisableAPB1(RCC_APB1ENR_TIM6EN, lp)
+
+/**
+ * @brief Resets the TIM6 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST)
+
+/**
+ * @brief Enables the TIM7 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp)
+
+/**
+ * @brief Disables the TIM7 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM7(lp) rccDisableAPB1(RCC_APB1ENR_TIM7EN, lp)
+
+/**
+ * @brief Resets the TIM7 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST)
+
+/**
+ * @brief Enables the TIM8 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp)
+
+/**
+ * @brief Disables the TIM8 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM8(lp) rccDisableAPB2(RCC_APB2ENR_TIM8EN, lp)
+
+/**
+ * @brief Resets the TIM8 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST)
+
+/**
+ * @brief Enables the TIM9peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM9(lp) rccEnableAPB2(RCC_APB2ENR_TIM9EN, lp)
+
+/**
+ * @brief Disables the TIM9 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM9(lp) rccDisableAPB2(RCC_APB2ENR_TIM9EN, lp)
+
+/**
+ * @brief Resets the TIM9 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM9() rccResetAPB2(RCC_APB2RSTR_TIM9RST)
+
+/**
+ * @brief Enables the TIM11 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM11(lp) rccEnableAPB2(RCC_APB2ENR_TIM11EN, lp)
+
+/**
+ * @brief Disables the TIM11 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM11(lp) rccDisableAPB2(RCC_APB2ENR_TIM11EN, lp)
+
+/**
+ * @brief Resets the TIM11 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM11() rccResetAPB2(RCC_APB2RSTR_TIM11RST)
+
+/**
+ * @brief Enables the TIM12 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM12(lp) rccEnableAPB1(RCC_APB1ENR_TIM12EN, lp)
+
+/**
+ * @brief Disables the TIM12 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM12(lp) rccDisableAPB1(RCC_APB1ENR_TIM12EN, lp)
+
+/**
+ * @brief Resets the TIM12 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM12() rccResetAPB1(RCC_APB1RSTR_TIM12RST)
+
+/**
+ * @brief Enables the TIM14 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM14(lp) rccEnableAPB1(RCC_APB1ENR_TIM14EN, lp)
+
+/**
+ * @brief Disables the TIM14 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableTIM14(lp) rccDisableAPB1(RCC_APB1ENR_TIM14EN, lp)
+
+/**
+ * @brief Resets the TIM14 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM14() rccResetAPB1(RCC_APB1RSTR_TIM14RST)
+/** @} */
+
+/**
+ * @name USART/UART peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp)
+
+/**
+ * @brief Disables the USART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp)
+
+/**
+ * @brief Resets the USART1 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST)
+
+/**
+ * @brief Enables the USART2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp)
+
+/**
+ * @brief Disables the USART2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp)
+
+/**
+ * @brief Resets the USART2 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST)
+
+/**
+ * @brief Enables the USART3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp)
+
+/**
+ * @brief Disables the USART3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableUSART3(lp) rccDisableAPB1(RCC_APB1ENR_USART3EN, lp)
+
+/**
+ * @brief Resets the USART3 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST)
+
+/**
+ * @brief Enables the USART6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART6(lp) rccEnableAPB2(RCC_APB2ENR_USART6EN, lp)
+
+/**
+ * @brief Disables the USART6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableUSART6(lp) rccDisableAPB2(RCC_APB2ENR_USART6EN, lp)
+
+/**
+ * @brief Enables the UART4 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp)
+
+/**
+ * @brief Disables the UART4 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableUART4(lp) rccDisableAPB1(RCC_APB1ENR_UART4EN, lp)
+
+/**
+ * @brief Resets the UART4 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST)
+
+/**
+ * @brief Enables the UART5 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp)
+
+/**
+ * @brief Disables the UART5 peripheral clock.
+ * @note The @p lp parameter is ignored in this family.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableUART5(lp) rccDisableAPB1(RCC_APB1ENR_UART5EN, lp)
+
+/**
+ * @brief Resets the UART5 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST)
+
+/**
+ * @brief Resets the USART6 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST)
+/** @} */
+
+/**
+ * @name LTDC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the LTDC peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableLTDC(lp) rccEnableAPB2(RCC_APB2ENR_LTDCEN, lp)
+
+/**
+ * @brief Disables the LTDC peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableLTDC(lp) rccDisableAPB2(RCC_APB2ENR_LTDCEN, lp)
+
+/**
+ * @brief Resets the LTDC peripheral.
+ *
+ * @api
+ */
+#define rccResetLTDC() rccResetAPB2(RCC_APB2RSTR_LTDCRST)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STM32_RCC_ */
+
+/** @} */
diff --git a/os/hal/ports/STM32/STM32F4xx/stm32_registry.h b/os/hal/ports/STM32/STM32F4xx/stm32_registry.h
new file mode 100644
index 000000000..8e15527f9
--- /dev/null
+++ b/os/hal/ports/STM32/STM32F4xx/stm32_registry.h
@@ -0,0 +1,296 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/stm32_registry.h
+ * @brief STM32F4xx capabilities registry.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef _STM32_REGISTRY_H_
+#define _STM32_REGISTRY_H_
+
+/*===========================================================================*/
+/* Platform capabilities. */
+/*===========================================================================*/
+
+/**
+ * @name STM32F4xx capabilities
+ * @{
+ */
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_ADC1_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC2 TRUE
+#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_ADC2_DMA_CHN 0x00001100
+
+#define STM32_HAS_ADC3 TRUE
+#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\
+ STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_ADC3_DMA_CHN 0x00000022
+
+#define STM32_HAS_ADC4 FALSE
+
+#define STM32_HAS_SDADC1 FALSE
+#define STM32_HAS_SDADC2 FALSE
+#define STM32_HAS_SDADC3 FALSE
+
+/* CAN attributes.*/
+#define STM32_HAS_CAN1 TRUE
+#define STM32_HAS_CAN2 TRUE
+#define STM32_CAN_MAX_FILTERS 28
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1 TRUE
+#define STM32_HAS_DAC2 FALSE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_HAS_DMA1 TRUE
+#define STM32_HAS_DMA2 TRUE
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH TRUE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_NUM_CHANNELS 23
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOH TRUE
+#if !defined(STM32F401xx)
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOI TRUE
+#else
+#define STM32_HAS_GPIOF FALSE
+#define STM32_HAS_GPIOG FALSE
+#define STM32_HAS_GPIOI FALSE
+#endif
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\
+ STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_I2C1_RX_DMA_CHN 0x00100001
+#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\
+ STM32_DMA_STREAM_ID_MSK(1, 6))
+#define STM32_I2C1_TX_DMA_CHN 0x11000000
+
+#define STM32_HAS_I2C2 TRUE
+#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_I2C2_RX_DMA_CHN 0x00007700
+#define STM32_I2C2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7)
+#define STM32_I2C2_TX_DMA_CHN 0x70000000
+
+#define STM32_HAS_I2C3 TRUE
+#define STM32_I2C3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2)
+#define STM32_I2C3_RX_DMA_CHN 0x00000300
+#define STM32_I2C3_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4)
+#define STM32_I2C3_TX_DMA_CHN 0x00030000
+
+/* RTC attributes.*/
+#define STM32_HAS_RTC TRUE
+#if defined(STM32F4XX) || defined(__DOXYGEN__)
+#define STM32_RTC_HAS_SUBSECONDS TRUE
+#else
+#define STM32_RTC_HAS_SUBSECONDS FALSE
+#endif
+#define STM32_RTC_IS_CALENDAR TRUE
+
+/* SDIO attributes.*/
+#define STM32_HAS_SDIO TRUE
+#define STM32_SDC_SDIO_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_SDC_SDIO_DMA_CHN 0x04004000
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\
+ STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_SPI1_RX_DMA_CHN 0x00000303
+#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_SPI1_TX_DMA_CHN 0x00303000
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3)
+#define STM32_SPI2_RX_DMA_CHN 0x00000000
+#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4)
+#define STM32_SPI2_TX_DMA_CHN 0x00000000
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 0) |\
+ STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_SPI3_RX_DMA_CHN 0x00000000
+#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(1, 7))
+#define STM32_SPI3_TX_DMA_CHN 0x00000000
+
+#if defined(STM32F427_437xx) || defined(STM32F429_439xx)
+#define STM32_HAS_SPI4 TRUE
+#define STM32_SPI4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 0) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_SPI4_RX_DMA_CHN 0x00005004
+#define STM32_SPI4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_SPI4_TX_DMA_CHN 0x00050040
+
+#define STM32_HAS_SPI5 TRUE
+#define STM32_SPI5_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3) | \
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_SPI5_RX_DMA_CHN 0x00702000
+#define STM32_SPI5_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) | \
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_SPI5_TX_DMA_CHN 0x07020000
+
+#define STM32_HAS_SPI6 TRUE
+#define STM32_SPI6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_SPI6_RX_DMA_CHN 0x01000000
+#define STM32_SPI6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_SPI6_TX_DMA_CHN 0x00100000
+
+#else /* !(defined(STM32F427_437xx) || defined(STM32F429_439xx)) */
+#define STM32_HAS_SPI4 FALSE
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+#endif /* !(defined(STM32F427_437xx) || defined(STM32F429_439xx)) */
+
+/* TIM attributes.*/
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 4
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM5 TRUE
+#define STM32_TIM5_IS_32BITS TRUE
+#define STM32_TIM5_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM9 TRUE
+#define STM32_TIM9_IS_32BITS FALSE
+#define STM32_TIM9_CHANNELS 2
+
+#define STM32_HAS_TIM10 TRUE
+#define STM32_TIM10_IS_32BITS FALSE
+#define STM32_TIM10_CHANNELS 2
+
+#define STM32_HAS_TIM11 TRUE
+#define STM32_TIM11_IS_32BITS FALSE
+#define STM32_TIM11_CHANNELS 2
+
+#define STM32_HAS_TIM12 TRUE
+#define STM32_TIM12_IS_32BITS FALSE
+#define STM32_TIM12_CHANNELS 2
+
+#define STM32_HAS_TIM13 TRUE
+#define STM32_TIM13_IS_32BITS FALSE
+#define STM32_TIM13_CHANNELS 2
+
+#define STM32_HAS_TIM14 TRUE
+#define STM32_TIM14_IS_32BITS FALSE
+#define STM32_TIM14_CHANNELS 2
+
+#define STM32_HAS_TIM15 FALSE
+#define STM32_HAS_TIM16 FALSE
+#define STM32_HAS_TIM17 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_USART1_RX_DMA_CHN 0x00400400
+#define STM32_USART1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 7)
+#define STM32_USART1_TX_DMA_CHN 0x40000000
+
+#define STM32_HAS_USART2 TRUE
+#define STM32_USART2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5)
+#define STM32_USART2_RX_DMA_CHN 0x00400000
+#define STM32_USART2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 6)
+#define STM32_USART2_TX_DMA_CHN 0x04000000
+
+#define STM32_HAS_USART3 TRUE
+#define STM32_USART3_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 1)
+#define STM32_USART3_RX_DMA_CHN 0x00000040
+#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_USART3_TX_DMA_CHN 0x00074000
+
+#define STM32_HAS_UART4 TRUE
+#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2)
+#define STM32_UART4_RX_DMA_CHN 0x00000400
+#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4)
+#define STM32_UART4_TX_DMA_CHN 0x00040000
+
+#define STM32_HAS_UART5 TRUE
+#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 0)
+#define STM32_UART5_RX_DMA_CHN 0x00000004
+#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 7)
+#define STM32_UART5_TX_DMA_CHN 0x40000000
+
+#define STM32_HAS_USART6 TRUE
+#define STM32_USART6_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1) |\
+ STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_USART6_RX_DMA_CHN 0x00000550
+#define STM32_USART6_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 6) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_USART6_TX_DMA_CHN 0x55000000
+
+/* USB attributes.*/
+#define STM32_HAS_USB FALSE
+#define STM32_HAS_OTG1 TRUE
+#define STM32_HAS_OTG2 TRUE
+/** @} */
+
+#endif /* _STM32_REGISTRY_H_ */
+
+/** @} */