aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/platforms/STM32L1xx
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal/platforms/STM32L1xx')
-rw-r--r--os/hal/platforms/STM32L1xx/adc_lld.c278
-rw-r--r--os/hal/platforms/STM32L1xx/adc_lld.h472
-rw-r--r--os/hal/platforms/STM32L1xx/hal_lld.c7
-rw-r--r--os/hal/platforms/STM32L1xx/hal_lld.h252
-rw-r--r--os/hal/platforms/STM32L1xx/platform.dox87
-rw-r--r--os/hal/platforms/STM32L1xx/platform.mk12
-rw-r--r--os/hal/platforms/STM32L1xx/stm32_dma.c349
-rw-r--r--os/hal/platforms/STM32L1xx/stm32_dma.h382
-rw-r--r--os/hal/platforms/STM32L1xx/stm32_rcc.h552
-rw-r--r--os/hal/platforms/STM32L1xx/stm32l1xx.h2
10 files changed, 2332 insertions, 61 deletions
diff --git a/os/hal/platforms/STM32L1xx/adc_lld.c b/os/hal/platforms/STM32L1xx/adc_lld.c
new file mode 100644
index 000000000..3d91a9991
--- /dev/null
+++ b/os/hal/platforms/STM32L1xx/adc_lld.c
@@ -0,0 +1,278 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file STM32L1xx/adc_lld.c
+ * @brief STM32L1xx ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* 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_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+/**
+ * @brief ADC interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(ADC1_IRQHandler) {
+ uint32_t sr;
+
+ CH_IRQ_PROLOGUE();
+
+ 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.*/
+
+ 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_DMA1_STREAM1;
+ ADCD1.dmamode = 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 |
+ STM32_DMA_CR_EN;
+#endif
+
+ /* The shared vector is initialized on driver initialization and never
+ disabled.*/
+ NVICEnableVector(ADC1_IRQn, CORTEX_PRIORITY_MASK(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_t b;
+ b = dmaStreamAllocate(adcp->dmastp,
+ STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ chDbgAssert(!b, "adc_lld_start(), #1", "stream already allocated");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR);
+ rccEnableADC1(FALSE);
+ }
+#endif /* STM32_ADC_USE_ADC1 */
+
+ /* 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 and analog part.*/
+ 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
+ }
+}
+
+/**
+ * @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 the buffer depth is greater than one then the half transfer interrupt
+ interrupt is enabled in order to allows 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);
+
+ /* ADC setup.*/
+ adcp->adc->SR = 0;
+ adcp->adc->SMPR1 = grpp->smpr1;
+ adcp->adc->SMPR2 = grpp->smpr2;
+ adcp->adc->SMPR3 = grpp->smpr3;
+ adcp->adc->SQR1 = grpp->sqr1;
+ adcp->adc->SQR2 = grpp->sqr2;
+ adcp->adc->SQR3 = grpp->sqr3;
+ adcp->adc->SQR4 = grpp->sqr4;
+ adcp->adc->SQR5 = grpp->sqr5;
+
+ /* 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;
+ adcp->adc->CR2 = grpp->cr2 | ADC_CR2_CONT | 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;
+}
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/os/hal/platforms/STM32L1xx/adc_lld.h b/os/hal/platforms/STM32L1xx/adc_lld.h
new file mode 100644
index 000000000..29b5ff8c5
--- /dev/null
+++ b/os/hal/platforms/STM32L1xx/adc_lld.h
@@ -0,0 +1,472 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file STM32L1xx/adc_lld.h
+ * @brief STM32L1xx 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 Triggers selection
+ * @{
+ */
+#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */
+/** @} */
+
+/**
+ * @name ADC clock divider settings
+ * @{
+ */
+#define ADC_CCR_ADCPRE_DIV1 0
+#define ADC_CCR_ADCPRE_DIV2 1
+#define ADC_CCR_ADCPRE_DIV4 2
+/** @} */
+
+/**
+ * @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.*/
+#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */
+#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */
+#define ADC_CHANNEL_IN19 19 /**< @brief External analog input 19. */
+#define ADC_CHANNEL_IN20 20 /**< @brief External analog input 20. */
+#define ADC_CHANNEL_IN21 21 /**< @brief External analog input 21. */
+#define ADC_CHANNEL_IN22 22 /**< @brief External analog input 22. */
+#define ADC_CHANNEL_IN23 23 /**< @brief External analog input 23. */
+#define ADC_CHANNEL_IN24 24 /**< @brief External analog input 24. */
+#define ADC_CHANNEL_IN25 25 /**< @brief External analog input 25. */
+/** @} */
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#define ADC_SAMPLE_4 0 /**< @brief 4 cycles sampling time. */
+#define ADC_SAMPLE_9 1 /**< @brief 9 cycles sampling time. */
+#define ADC_SAMPLE_16 2 /**< @brief 16 cycles sampling time. */
+#define ADC_SAMPLE_24 3 /**< @brief 24 cycles sampling time. */
+#define ADC_SAMPLE_48 4 /**< @brief 48 cycles sampling time. */
+#define ADC_SAMPLE_96 5 /**< @brief 96 cycles sampling time. */
+#define ADC_SAMPLE_192 6 /**< @brief 192 cycles sampling time. */
+#define ADC_SAMPLE_384 7 /**< @brief 384 cycles sampling time. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @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 TRUE
+#endif
+
+/**
+ * @brief ADC common clock divider.
+ * @note This setting is influenced by the VDDA voltage and other
+ * external conditions, please refer to the STM32L15x datasheet
+ * for more info.<br>
+ * See section 6.3.15 "12-bit ADC characteristics".
+ */
+#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV1
+#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 ADC interrupt priority level setting.
+ */
+#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
+
+/** @} */
+
+/*===========================================================================*/
+/* 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_ADC1
+#error "ADC driver activated but no ADC peripheral assigned"
+#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
+ */
+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_t 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
+ * 20...25.
+ */
+ uint32_t smpr1;
+ /**
+ * @brief ADC SMPR2 register initialization data.
+ * @details In this field must be specified the sample times for channels
+ * 10...19.
+ */
+ uint32_t smpr2;
+ /**
+ * @brief ADC SMPR3 register initialization data.
+ * @details In this field must be specified the sample times for channels
+ * 0...9.
+ */
+ uint32_t smpr3;
+ /**
+ * @brief ADC SQR1 register initialization data.
+ * @details Conversion group sequence 25...27 + sequence length.
+ */
+ uint32_t sqr1;
+ /**
+ * @brief ADC SQR2 register initialization data.
+ * @details Conversion group sequence 19...24.
+ */
+ uint32_t sqr2;
+ /**
+ * @brief ADC SQR3 register initialization data.
+ * @details Conversion group sequence 13...18.
+ */
+ uint32_t sqr3;
+ /**
+ * @brief ADC SQR3 register initialization data.
+ * @details Conversion group sequence 7...12.
+ */
+ uint32_t sqr4;
+ /**
+ * @brief ADC SQR3 register initialization data.
+ * @details Conversion group sequence 1...6.
+ */
+ uint32_t sqr5;
+} 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 *thread;
+#endif
+#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+#if CH_USE_MUTEXES || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ Mutex mutex;
+#elif CH_USE_SEMAPHORES
+ Semaphore semaphore;
+#endif
+#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 SMA 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_SQR5_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
+#define ADC_SQR5_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
+#define ADC_SQR5_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
+#define ADC_SQR5_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
+#define ADC_SQR5_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
+#define ADC_SQR5_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
+
+#define ADC_SQR4_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
+#define ADC_SQR4_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
+#define ADC_SQR4_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
+#define ADC_SQR4_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
+#define ADC_SQR4_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
+#define ADC_SQR4_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
+
+#define ADC_SQR3_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
+#define ADC_SQR3_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
+#define ADC_SQR3_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
+#define ADC_SQR3_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
+#define ADC_SQR3_SQ17_N(n) ((n) << 20) /**< @brief 17th channel in seq.*/
+#define ADC_SQR3_SQ18_N(n) ((n) << 25) /**< @brief 18th channel in seq.*/
+
+#define ADC_SQR2_SQ19_N(n) ((n) << 0) /**< @brief 19th channel in seq.*/
+#define ADC_SQR2_SQ20_N(n) ((n) << 5) /**< @brief 20th channel in seq.*/
+#define ADC_SQR2_SQ21_N(n) ((n) << 10) /**< @brief 21th channel in seq.*/
+#define ADC_SQR2_SQ22_N(n) ((n) << 15) /**< @brief 22th channel in seq.*/
+#define ADC_SQR2_SQ23_N(n) ((n) << 20) /**< @brief 23th channel in seq.*/
+#define ADC_SQR2_SQ24_N(n) ((n) << 25) /**< @brief 24th channel in seq.*/
+
+#define ADC_SQR1_SQ25_N(n) ((n) << 0) /**< @brief 25th channel in seq.*/
+#define ADC_SQR1_SQ26_N(n) ((n) << 5) /**< @brief 26th channel in seq.*/
+#define ADC_SQR1_SQ27_N(n) ((n) << 10) /**< @brief 27th channel in seq.*/
+/** @} */
+
+/**
+ * @name Sampling rate settings helper macros
+ * @{
+ */
+#define ADC_SMPR3_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
+#define ADC_SMPR3_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
+#define ADC_SMPR3_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
+#define ADC_SMPR3_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
+#define ADC_SMPR3_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
+#define ADC_SMPR3_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
+#define ADC_SMPR3_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
+#define ADC_SMPR3_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
+#define ADC_SMPR3_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
+#define ADC_SMPR3_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
+
+#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
+#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
+#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
+#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
+#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
+#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
+#define ADC_SMPR2_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor
+ sampling time. */
+#define ADC_SMPR2_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference
+ sampling time. */
+#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 sampling time. */
+#define ADC_SMPR2_SMP_AN19(n) ((n) << 27) /**< @brief AN19 sampling time. */
+
+#define ADC_SMPR1_SMP_AN20(n) ((n) << 0) /**< @brief AN20 sampling time. */
+#define ADC_SMPR1_SMP_AN21(n) ((n) << 3) /**< @brief AN21 sampling time. */
+#define ADC_SMPR1_SMP_AN22(n) ((n) << 6) /**< @brief AN22 sampling time. */
+#define ADC_SMPR1_SMP_AN23(n) ((n) << 9) /**< @brief AN23 sampling time. */
+#define ADC_SMPR1_SMP_AN24(n) ((n) << 12) /**< @brief AN24 sampling time. */
+#define ADC_SMPR1_SMP_AN25(n) ((n) << 15) /**< @brief AN25 sampling time. */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#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);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* _ADC_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/STM32L1xx/hal_lld.c b/os/hal/platforms/STM32L1xx/hal_lld.c
index 9a8265365..c59aa3f1c 100644
--- a/os/hal/platforms/STM32L1xx/hal_lld.c
+++ b/os/hal/platforms/STM32L1xx/hal_lld.c
@@ -59,10 +59,9 @@
void hal_lld_init(void) {
/* Reset of all peripherals.*/
-// RCC->APB1RSTR = 0xFFFFFFFF;
-// RCC->APB2RSTR = 0xFFFFFFFF;
-// RCC->APB1RSTR = 0;
-// RCC->APB2RSTR = 0;
+ rccResetAHB(!RCC_AHBRSTR_FLITFRST);
+ rccResetAPB1(!0);
+ rccResetAPB2(!RCC_APB2RSTR_SYSCFGRST);
/* SysTick initialization using the system clock.*/
SysTick->LOAD = STM32_HCLK / CH_FREQUENCY - 1;
diff --git a/os/hal/platforms/STM32L1xx/hal_lld.h b/os/hal/platforms/STM32L1xx/hal_lld.h
index 97cfde0b7..b25bad51d 100644
--- a/os/hal/platforms/STM32L1xx/hal_lld.h
+++ b/os/hal/platforms/STM32L1xx/hal_lld.h
@@ -37,40 +37,52 @@
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
-/* Tricks required to make the TRUE/FALSE declaration inside the library
- compatible.*/
-#undef FALSE
-#undef TRUE
-#include "stm32l1xx.h"
-#define FALSE 0
-#define TRUE (!FALSE)
+#include "stm32.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
- * @brief Platform name.
+ * @name Platform identification
+ * @{
*/
-#define PLATFORM_NAME "STM32L Ultra Low Power Medium Density"
+#define PLATFORM_NAME "STM32L1 Ultra Low Power Medium Density"
+/** @} */
+/**
+ * @name Internal clock sources
+ * @{
+ */
#define STM32_HSICLK 16000000 /**< High speed internal clock. */
#define STM32_LSICLK 38000 /**< Low speed internal clock. */
+/** @} */
-/* PWR_CR register bits definitions.*/
+/**
+ * @name PWR_CR register bits definitions
+ * @{
+ */
#define STM32_VOS_MASK (3 << 11) /**< Core voltage mask. */
#define STM32_VOS_1P8 (1 << 11) /**< Core voltage 1.8 Volts. */
#define STM32_VOS_1P5 (2 << 11) /**< Core voltage 1.5 Volts. */
#define STM32_VOS_1P2 (3 << 11) /**< Core voltage 1.2 Volts. */
+/** @} */
-/* RCC_CR register bits definitions.*/
+/**
+ * @name RCC_CR register bits definitions
+ * @{
+ */
#define STM32_RTCPRE_MASK (3 << 29) /**< RTCPRE mask. */
#define STM32_RTCPRE_DIV2 (0 << 29) /**< HSE divided by 2. */
#define STM32_RTCPRE_DIV4 (1 << 29) /**< HSE divided by 4. */
#define STM32_RTCPRE_DIV8 (2 << 29) /**< HSE divided by 2. */
#define STM32_RTCPRE_DIV16 (3 << 29) /**< HSE divided by 16. */
+/** @} */
-/* RCC_CFGR register bits definitions.*/
+/**
+ * @name RCC_CFGR register bits definitions
+ * @{
+ */
#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */
#define STM32_SW_HSI (1 << 0) /**< SYSCLK source is HSI. */
#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */
@@ -115,8 +127,12 @@
#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 1. */
#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 1. */
#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 1. */
+/** @} */
-/* RCC_ICSCR register bits definitions.*/
+/**
+ * @name RCC_ICSCR register bits definitions
+ * @{
+ */
#define STM32_MSIRANGE_MASK (7 << 13) /**< MSIRANGE field mask. */
#define STM32_MSIRANGE_64K (0 << 13) /**< 64KHz nominal. */
#define STM32_MSIRANGE_128K (1 << 13) /**< 128KHz nominal. */
@@ -125,29 +141,51 @@
#define STM32_MSIRANGE_1M (4 << 13) /**< 1MHz nominal. */
#define STM32_MSIRANGE_2M (5 << 13) /**< 2MHz nominal. */
#define STM32_MSIRANGE_4M (6 << 13) /**< 4MHz nominal */
+/** @} */
-/* RCC_CSR register bits definitions.*/
+/**
+ * @name RCC_CSR register bits definitions
+ * @{
+ */
#define STM32_RTCSEL_MASK (3 << 16) /**< RTC source mask. */
#define STM32_RTCSEL_NOCLOCK (0 << 16) /**< No RTC source. */
#define STM32_RTCSEL_LSE (1 << 16) /**< RTC source is LSE. */
#define STM32_RTCSEL_LSI (2 << 16) /**< RTC source is LSI. */
#define STM32_RTCSEL_HSEDIV (3 << 16) /**< RTC source is HSE divided. */
+/** @} */
-/* STM32L1xx capabilities.*/
+/*===========================================================================*/
+/* Platform capabilities. */
+/*===========================================================================*/
+
+/**
+ * @name STM32L1xx capabilities
+ * @{
+ */
+/* ADC attributes.*/
#define STM32_HAS_ADC1 TRUE
#define STM32_HAS_ADC2 FALSE
#define STM32_HAS_ADC3 FALSE
+/* CAN attributes.*/
#define STM32_HAS_CAN1 FALSE
#define STM32_HAS_CAN2 FALSE
+/* DAC attributes.*/
#define STM32_HAS_DAC TRUE
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA FALSE
#define STM32_HAS_DMA1 TRUE
#define STM32_HAS_DMA2 FALSE
+/* ETH attributes.*/
#define STM32_HAS_ETH FALSE
+/* 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
@@ -156,18 +194,39 @@
#define STM32_HAS_GPIOF FALSE
#define STM32_HAS_GPIOG FALSE
#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOI FALSE
+/* I2C attributes.*/
#define STM32_HAS_I2C1 TRUE
#define STM32_HAS_I2C2 TRUE
+#define STM32_HAS_I2C3 FALSE
+/* RTC attributes.*/
#define STM32_HAS_RTC TRUE
+/* SDIO attributes.*/
#define STM32_HAS_SDIO FALSE
+/* SPI attributes.*/
#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 2)
+#define STM32_SPI1_RX_DMA_CHN 0x00000000
+#define STM32_SPI1_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 3)
+#define STM32_SPI1_TX_DMA_CHN 0x00000000
+
#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 4)
+#define STM32_SPI2_RX_DMA_CHN 0x00000000
+#define STM32_SPI2_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(1, 5)
+#define STM32_SPI2_TX_DMA_CHN 0x00000000
+
#define STM32_HAS_SPI3 FALSE
+#define STM32_SPI3_RX_DMA_MSK 0
+#define STM32_SPI3_RX_DMA_CHN 0x00000000
+#define STM32_SPI3_TX_DMA_MSK 0
+#define STM32_SPI3_TX_DMA_CHN 0x00000000
+/* TIM attributes.*/
#define STM32_HAS_TIM1 FALSE
#define STM32_HAS_TIM2 TRUE
#define STM32_HAS_TIM3 TRUE
@@ -186,20 +245,116 @@
#define STM32_HAS_TIM16 FALSE
#define STM32_HAS_TIM17 FALSE
+/* USART attributes.*/
#define STM32_HAS_USART1 TRUE
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_USART1_RX_DMA_CHN 0x00000000
+#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_USART1_TX_DMA_CHN 0x00000000
+
#define STM32_HAS_USART2 TRUE
+#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
+#define STM32_USART2_RX_DMA_CHN 0x00000000
+#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
+#define STM32_USART2_TX_DMA_CHN 0x00000000
+
#define STM32_HAS_USART3 TRUE
-#define STM32_HAS_UART3 FALSE
-#define STM32_HAS_UART4 FALSE
+#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_USART3_RX_DMA_CHN 0x00000000
+#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_USART3_TX_DMA_CHN 0x00000000
+#define STM32_HAS_UART4 FALSE
+#define STM32_UART4_RX_DMA_MSK 0
+#define STM32_UART4_RX_DMA_CHN 0x00000000
+#define STM32_UART4_TX_DMA_MSK 0
+#define STM32_UART4_TX_DMA_CHN 0x00000000
+
+#define STM32_HAS_UART5 FALSE
+#define STM32_UART5_RX_DMA_MSK 0
+#define STM32_UART5_RX_DMA_CHN 0x00000000
+#define STM32_UART5_TX_DMA_MSK 0
+#define STM32_UART5_TX_DMA_CHN 0x00000000
+
+#define STM32_HAS_USART6 FALSE
+#define STM32_USART6_RX_DMA_MSK 0
+#define STM32_USART6_RX_DMA_CHN 0x00000000
+#define STM32_USART6_TX_DMA_MSK 0
+#define STM32_USART6_TX_DMA_CHN 0x00000000
+
+/* USB attributes.*/
#define STM32_HAS_USB TRUE
#define STM32_HAS_OTG1 FALSE
+#define STM32_HAS_OTG2 FALSE
+/** @} */
+
+/*===========================================================================*/
+/* Platform specific friendly IRQ names. */
+/*===========================================================================*/
+
+/**
+ * @name IRQ VECTOR names
+ * @{
+ */
+#define WWDG_IRQHandler Vector40 /**< Window Watchdog. */
+#define PVD_IRQHandler Vector44 /**< PVD through EXTI Line
+ detect. */
+#define TAMPER_STAMP_IRQHandler Vector48 /**< Tamper and Time Stamp
+ through EXTI. */
+#define RTC_WKUP_IRQHandler Vector4C /**< RTC Wakeup Timer through
+ EXTI. */
+#define FLASH_IRQHandler Vector50 /**< Flash. */
+#define RCC_IRQHandler Vector54 /**< RCC. */
+#define EXTI0_IRQHandler Vector58 /**< EXTI Line 0. */
+#define EXTI1_IRQHandler Vector5C /**< EXTI Line 1. */
+#define EXTI2_IRQHandler Vector60 /**< EXTI Line 2. */
+#define EXTI3_IRQHandler Vector64 /**< EXTI Line 3. */
+#define EXTI4_IRQHandler Vector68 /**< EXTI Line 4. */
+#define DMA1_Ch1_IRQHandler Vector6C /**< DMA1 Channel 1. */
+#define DMA1_Ch2_IRQHandler Vector70 /**< DMA1 Channel 2. */
+#define DMA1_Ch3_IRQHandler Vector74 /**< DMA1 Channel 3. */
+#define DMA1_Ch4_IRQHandler Vector78 /**< DMA1 Channel 4. */
+#define DMA1_Ch5_IRQHandler Vector7C /**< DMA1 Channel 5. */
+#define DMA1_Ch6_IRQHandler Vector80 /**< DMA1 Channel 6. */
+#define DMA1_Ch7_IRQHandler Vector84 /**< DMA1 Channel 7. */
+#define ADC1_IRQHandler Vector88 /**< ADC1. */
+#define USB_HP_IRQHandler Vector8C /**< USB High Priority. */
+#define USB_LP_IRQHandler Vector90 /**< USB Low Priority. */
+#define DAC_IRQHandler Vector94 /**< DAC. */
+#define COMP_IRQHandler Vector98 /**< Comparator through EXTI. */
+#define EXTI9_5_IRQHandler Vector9C /**< EXTI Line 9..5. */
+#define TIM9_IRQHandler VectorA0 /**< TIM9. */
+#define TIM10_IRQHandler VectorA4 /**< TIM10. */
+#define TIM11_IRQHandler VectorA8 /**< TIM11. */
+#define LCD_IRQHandler VectorAC /**< LCD. */
+#define TIM2_IRQHandler VectorB0 /**< TIM2. */
+#define TIM3_IRQHandler VectorB4 /**< TIM3. */
+#define TIM4_IRQHandler VectorB8 /**< TIM4. */
+#define I2C1_EV_IRQHandler VectorBC /**< I2C1 Event. */
+#define I2C1_ER_IRQHandler VectorC0 /**< I2C1 Error. */
+#define I2C2_EV_IRQHandler VectorC4 /**< I2C2 Event. */
+#define I2C2_ER_IRQHandler VectorC8 /**< I2C2 Error. */
+#define SPI1_IRQHandler VectorCC /**< SPI1. */
+#define SPI2_IRQHandler VectorD0 /**< SPI2. */
+#define USART1_IRQHandler VectorD4 /**< USART1. */
+#define USART2_IRQHandler VectorD8 /**< USART2. */
+#define USART3_IRQHandler VectorDC /**< USART3. */
+#define EXTI15_10_IRQHandler VectorE0 /**< EXTI Line 15..10. */
+#define RTC_Alarm_IRQHandler VectorE4 /**< RTC Alarm through EXTI. */
+#define USB_FS_WKUP_IRQHandler VectorE8 /**< USB Wakeup from suspend. */
+#define TIM6_IRQHandler VectorEC /**< TIM6. */
+#define TIM7_IRQHandler VectorF0 /**< TIM7. */
+/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
+ * @name Configuration options
+ * @{
+ */
+/**
* @brief Disables the PWR/RCC initialization in the HAL.
*/
#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__)
@@ -357,6 +512,7 @@
#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__)
#define STM32_RTCPRE STM32_RTCPRE_DIV2
#endif
+/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
@@ -365,19 +521,34 @@
/* Voltage related limits.*/
#if (STM32_VOS == STM32_VOS_1P8) || defined(__DOXYGEN__)
/**
- * @brief Maximum HSECLK at current voltage setting.
+ * @brief Maximum HSE clock frequency at current voltage setting.
*/
-#define STM32_HSECLK_MAX 32000000#if
+#define STM32_HSECLK_MAX 32000000
/**
- * @brief Maximum SYSCLK at current voltage setting.
+ * @brief Maximum SYSCLK clock frequency at current voltage setting.
*/
#define STM32_SYSCLK_MAX 32000000
/**
- * @brief Maximum PLLCLKOUT at current voltage setting.
+ * @brief Maximum VCO clock frequency at current voltage setting.
+ */
+#define STM32_PLLVCO_MAX 96000000
+
+/**
+ * @brief Minimum VCO clock frequency at current voltage setting.
+ */
+#define STM32_PLLVCO_MIN 6000000
+
+/**
+ * @brief Maximum APB1 clock frequency.
+ */
+#define STM32_PCLK1_MAX 32000000
+
+/**
+ * @brief Maximum APB2 clock frequency.
*/
-#define STM32_PLLCLKOUT_MAX 96000000
+#define STM32_PCLK2_MAX 32000000
/**
* @brief Maximum frequency not requiring a wait state for flash accesses.
@@ -392,13 +563,19 @@
#elif STM32_VOS == STM32_VOS_1P5
#define STM32_HSECLK_MAX 16000000
#define STM32_SYSCLK_MAX 16000000
-#define STM32_PLLCLKOUT_MAX 48000000
+#define STM32_PLLVCO_MAX 48000000
+#define STM32_PLLVCO_MIN 6000000
+#define STM32_PCLK1_MAX 16000000
+#define STM32_PCLK2_MAX 16000000
#define STM32_0WS_THRESHOLD 8000000
#define STM32_HSI_AVAILABLE TRUE
#elif STM32_VOS == STM32_VOS_1P2
#define STM32_HSECLK_MAX 4000000
#define STM32_SYSCLK_MAX 4000000
-#define STM32_PLLCLKOUT_MAX 24000000
+#define STM32_PLLVCO_MAX 24000000
+#define STM32_PLLVCO_MIN 6000000
+#define STM32_PCLK1_MAX 4000000
+#define STM32_PCLK2_MAX 4000000
#define STM32_0WS_THRESHOLD 2000000
#define STM32_HSI_AVAILABLE FALSE
#else
@@ -458,11 +635,11 @@
#if (STM32_LSECLK < 1000) || (STM32_LSECLK > 1000000)
#error "STM32_LSECLK outside acceptable range (1...1000KHz)"
#endif
-#else /* !#if STM32_LSE_ENABLED */
+#else /* !STM32_LSE_ENABLED */
#if STM_RTCCLK == STM32_LSECLK
#error "required LSE clock is not enabled"
#endif
-#endif /* !#if STM32_LSE_ENABLED */
+#endif /* !STM32_LSE_ENABLED */
/* PLL related checks.*/
#if STM32_USB_CLOCK_ENABLED || \
@@ -537,8 +714,8 @@
#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLMUL_VALUE)
/* PLL output frequency range check.*/
-#if (STM32_PLLVCO < 6000000) || (STM32_PLLVCO > 96000000)
-#error "STM32_PLLVCO outside acceptable range (6...96MHz)"
+#if (STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX)
+#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)"
#endif
/**
@@ -643,8 +820,8 @@
#endif
/* APB1 frequency check.*/
-#if STM32_PCLK2 > STM32_SYSCLK_MAX
-#error "STM32_PCLK1 exceeding maximum frequency (STM32_SYSCLK_MAX)"
+#if STM32_PCLK1 > STM32_PCLK1_MAX
+#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)"
#endif
/**
@@ -665,8 +842,8 @@
#endif
/* APB2 frequency check.*/
-#if STM32_PCLK2 > STM32_SYSCLK_MAX
-#error "STM32_PCLK2 exceeding maximum frequency (STM32_SYSCLK_MAX)"
+#if STM32_PCLK2 > STM32_PCLK2_MAX
+#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)"
#endif
/**
@@ -711,13 +888,13 @@
* @brief HSE divider toward RTC clock.
*/
#if (STM32_RTCPRE == STM32_RTCPRE_DIV2) || defined(__DOXYGEN__)
-#define STM32_HSEDIVCLK (HSECLK / 2)
+#define STM32_HSEDIVCLK (STM32_HSECLK / 2)
#elif (STM32_RTCPRE == STM32_RTCPRE_DIV4) || defined(__DOXYGEN__)
-#define STM32_HSEDIVCLK (HSECLK / 4)
+#define STM32_HSEDIVCLK (STM32_HSECLK / 4)
#elif (STM32_RTCPRE == STM32_RTCPRE_DIV8) || defined(__DOXYGEN__)
-#define STM32_HSEDIVCLK (HSECLK / 8)
+#define STM32_HSEDIVCLK (STM32_HSECLK / 8)
#elif (STM32_RTCPRE == STM32_RTCPRE_DIV16) || defined(__DOXYGEN__)
-#define STM32_HSEDIVCLK (HSECLK / 16)
+#define STM32_HSEDIVCLK (STM32_HSECLK / 16)
#else
#error "invalid STM32_RTCPRE value specified"
#endif
@@ -787,8 +964,9 @@
/* External declarations. */
/*===========================================================================*/
-/* STM32 DMA support code.*/
+/* STM32 DMA and RCC helpers.*/
#include "stm32_dma.h"
+#include "stm32_rcc.h"
#ifdef __cplusplus
extern "C" {
diff --git a/os/hal/platforms/STM32L1xx/platform.dox b/os/hal/platforms/STM32L1xx/platform.dox
index 7abe18e5e..cd244a2c9 100644
--- a/os/hal/platforms/STM32L1xx/platform.dox
+++ b/os/hal/platforms/STM32L1xx/platform.dox
@@ -20,7 +20,7 @@
/**
* @defgroup STM32L1xx_DRIVERS STM32L1xx Drivers
- * @details This section describes all the supported drivers on the STM32F1xx
+ * @details This section describes all the supported drivers on the STM32L1xx
* platform and the implementation details of the single drivers.
*
* @ingroup platforms
@@ -47,18 +47,36 @@
*/
/**
- * @defgroup STM32L1xx_DMA STM32L1xx DMA Support
- * @details This DMA helper driver is used by the other drivers in order to
- * access the shared DMA resources in a consistent way.
+ * @defgroup STM32L1xx_ADC STM32L1xx ADC Support
+ * @details The STM32L1xx ADC driver supports the ADC peripherals using DMA
+ * channels for maximum performance.
*
- * @section stm32l1xx_dma_1 Supported HW resources
- * The DMA driver can support any of the following hardware resources:
+ * @section stm32l1xx_adc_1 Supported HW resources
+ * - ADC1.
* - DMA1.
* .
- * @section stm32l1xx_dma_2 STM32L1xx DMA driver implementation features
- * - Automatic DMA clock stop when not in use by other drivers.
- * - Exports helper functions/macros to the other drivers that share the
- * DMA resource.
+ * @section stm32l1xx_adc_2 STM32L1xx ADC driver implementation features
+ * - Clock stop for reduced power usage when the driver is in stop state.
+ * - Streaming conversion using DMA for maximum performance.
+ * - Programmable ADC interrupt priority level.
+ * - Programmable DMA bus priority for each DMA channel.
+ * - Programmable DMA interrupt priority for each DMA channel.
+ * - DMA and ADC errors detection.
+ * .
+ * @ingroup STM32L1xx_DRIVERS
+ */
+
+/**
+ * @defgroup STM32L1xx_EXT STM32L1xx EXT Support
+ * @details The STM32L1xx EXT driver uses the EXTI peripheral.
+ *
+ * @section stm32l1xx_ext_1 Supported HW resources
+ * - EXTI.
+ * .
+ * @section stm32l1xx_ext_2 STM32L1xx EXT driver implementation features
+ * - Each EXTI channel can be independently enabled and programmed.
+ * - Programmable EXTI interrupts priority level.
+ * - Capability to work as event sources (WFE) rather than interrupt sources.
* .
* @ingroup STM32L1xx_DRIVERS
*/
@@ -128,8 +146,7 @@
* - @p PAL_MODE_INPUT_ANALOG.
* - @p PAL_MODE_OUTPUT_PUSHPULL.
* - @p PAL_MODE_OUTPUT_OPENDRAIN.
- * - @p PAL_MODE_STM32L1xx_ALTERNATE_PUSHPULL (non standard).
- * - @p PAL_MODE_STM32L1xx_ALTERNATE_OPENDRAIN (non standard).
+ * - @p PAL_MODE_ALTERNATE (non standard).
* .
* Any attempt to setup an invalid mode is ignored.
*
@@ -151,7 +168,6 @@
* - TIM2.
* - TIM3.
* - TIM4.
- * - TIM5.
* .
* @section stm32l1xx_pwm_2 STM32L1xx PWM driver implementation features
* - Each timer can be independently enabled and programmed. Unused
@@ -220,9 +236,7 @@
* - USART1.
* - USART2.
* - USART3 (where present).
- * - UART4 (where present).
* - DMA1.
- * - DMA2 (where present).
* .
* @section stm32l1xx_uart_2 STM32L1xx UART driver implementation features
* - Clock stop for reduced power usage when the driver is in stop state.
@@ -252,3 +266,46 @@
* .
* @ingroup STM32L1xx_DRIVERS
*/
+
+/**
+ * @defgroup STM32L1xx_PLATFORM_DRIVERS STM32L1xx Platform Drivers
+ * @details Platform support drivers. Platform drivers do not implement HAL
+ * standard driver templates, their role is to support platform
+ * specific functionalities.
+ *
+ * @ingroup STM32L1xx_DRIVERS
+ */
+
+/**
+ * @defgroup STM32L1xx_DMA STM32L1xx DMA Support
+ * @details This DMA helper driver is used by the other drivers in order to
+ * access the shared DMA resources in a consistent way.
+ *
+ * @section stm32l1xx_dma_1 Supported HW resources
+ * The DMA driver can support any of the following hardware resources:
+ * - DMA1.
+ * .
+ * @section stm32l1xx_dma_2 STM32L1xx DMA driver implementation features
+ * - Exports helper functions/macros to the other drivers that share the
+ * DMA resource.
+ * - Automatic DMA clock stop when not in use by any driver.
+ * - DMA streams and interrupt vectors sharing among multiple drivers.
+ * .
+ * @ingroup STM32L1xx_PLATFORM_DRIVERS
+ */
+
+/**
+ * @defgroup STM32L1xx_RCC STM32L1xx RCC Support
+ * @details This RCC helper driver is used by the other drivers in order to
+ * access the shared RCC resources in a consistent way.
+ *
+ * @section stm32f1xx_rcc_1 Supported HW resources
+ * - RCC.
+ * .
+ * @section stm32l1xx_rcc_2 STM32L1xx RCC driver implementation features
+ * - Peripherals reset.
+ * - Peripherals clock enable.
+ * - Periplerals clock disable.
+ * .
+ * @ingroup STM32L1xx_PLATFORM_DRIVERS
+ */
diff --git a/os/hal/platforms/STM32L1xx/platform.mk b/os/hal/platforms/STM32L1xx/platform.mk
index 348722671..301187e71 100644
--- a/os/hal/platforms/STM32L1xx/platform.mk
+++ b/os/hal/platforms/STM32L1xx/platform.mk
@@ -1,13 +1,15 @@
# List of all the STM32L1xx platform files.
-PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32L1xx/hal_lld.c \
+PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32L1xx/stm32_dma.c \
+ ${CHIBIOS}/os/hal/platforms/STM32L1xx/hal_lld.c \
+ ${CHIBIOS}/os/hal/platforms/STM32L1xx/adc_lld.c \
+ ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \
+ ${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/gpt_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/icu_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/pwm_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/serial_lld.c \
- ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \
- ${CHIBIOS}/os/hal/platforms/STM32/DMAv1/spi_lld.c \
- ${CHIBIOS}/os/hal/platforms/STM32/DMAv1/uart_lld.c \
- ${CHIBIOS}/os/hal/platforms/STM32/DMAv1/stm32_dma.c \
+ ${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \
+ ${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/USBv1/usb_lld.c
# Required include directories
diff --git a/os/hal/platforms/STM32L1xx/stm32_dma.c b/os/hal/platforms/STM32L1xx/stm32_dma.c
new file mode 100644
index 000000000..e49c419d9
--- /dev/null
+++ b/os/hal/platforms/STM32L1xx/stm32_dma.c
@@ -0,0 +1,349 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file STM32L1xx/stm32_dma.c
+ * @brief DMA helper driver code.
+ *
+ * @addtogroup STM32L1xx_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
+ * IRSs when allocating streams.
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring DMA services
+ has been enabled.*/
+#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Mask of the DMA1 streams in @p dma_streams_mask.
+ */
+#define STM32_DMA1_STREAMS_MASK 0x0000007F
+
+/**
+ * @brief Mask of the DMA2 streams in @p dma_streams_mask.
+ */
+#define STM32_DMA2_STREAMS_MASK 0x00000F80
+
+/**
+ * @brief Post-reset value of the stream CCR register.
+ */
+#define STM32_DMA_CCR_RESET_VALUE 0x00000000
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA streams descriptors.
+ * @details This table keeps the association between an unique stream
+ * identifier and the involved physical registers.
+ * @note Don't use this array directly, use the appropriate wrapper macros
+ * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc.
+ */
+const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
+ {DMA1_Channel1, &DMA1->IFCR, 0, 0, DMA1_Channel1_IRQn},
+ {DMA1_Channel2, &DMA1->IFCR, 4, 1, DMA1_Channel2_IRQn},
+ {DMA1_Channel3, &DMA1->IFCR, 8, 2, DMA1_Channel3_IRQn},
+ {DMA1_Channel4, &DMA1->IFCR, 12, 3, DMA1_Channel4_IRQn},
+ {DMA1_Channel5, &DMA1->IFCR, 16, 4, DMA1_Channel5_IRQn},
+ {DMA1_Channel6, &DMA1->IFCR, 20, 5, DMA1_Channel6_IRQn},
+ {DMA1_Channel7, &DMA1->IFCR, 24, 6, DMA1_Channel7_IRQn}
+};
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA ISR redirector type.
+ */
+typedef struct {
+ stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */
+ void *dma_param; /**< @brief DMA callback parameter. */
+} dma_isr_redir_t;
+
+/**
+ * @brief Mask of the allocated streams.
+ */
+static uint32_t dma_streams_mask;
+
+/**
+ * @brief DMA IRQ redirectors.
+ */
+static dma_isr_redir_t dma_isr_redir[STM32_DMA_STREAMS];
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA1 stream 1 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 0) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 0;
+ if (dma_isr_redir[0].dma_func)
+ dma_isr_redir[0].dma_func(dma_isr_redir[0].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 2 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 4) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 4;
+ if (dma_isr_redir[1].dma_func)
+ dma_isr_redir[1].dma_func(dma_isr_redir[1].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 3 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 8) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 8;
+ if (dma_isr_redir[2].dma_func)
+ dma_isr_redir[2].dma_func(dma_isr_redir[2].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 4 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 12) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 12;
+ if (dma_isr_redir[3].dma_func)
+ dma_isr_redir[3].dma_func(dma_isr_redir[3].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 5 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 16) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 16;
+ if (dma_isr_redir[4].dma_func)
+ dma_isr_redir[4].dma_func(dma_isr_redir[4].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 6 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 20) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 20;
+ if (dma_isr_redir[5].dma_func)
+ dma_isr_redir[5].dma_func(dma_isr_redir[5].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 7 shared interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(DMA1_Ch7_IRQHandler) {
+ uint32_t flags;
+
+ CH_IRQ_PROLOGUE();
+
+ flags = (DMA1->ISR >> 24) & STM32_DMA_ISR_MASK;
+ DMA1->IFCR = STM32_DMA_ISR_MASK << 24;
+ if (dma_isr_redir[6].dma_func)
+ dma_isr_redir[6].dma_func(dma_isr_redir[6].dma_param, flags);
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA helper initialization.
+ *
+ * @init
+ */
+void dmaInit(void) {
+ int i;
+
+ dma_streams_mask = 0;
+ for (i = 0; i < STM32_DMA_STREAMS; i++) {
+ _stm32_dma_streams[i].channel->CCR = 0;
+ dma_isr_redir[i].dma_func = NULL;
+ }
+ DMA1->IFCR = 0xFFFFFFFF;
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ * @pre The stream must not be already in use or an error is returned.
+ * @post The stream is allocated and the default ISR handler redirected
+ * to the specified function.
+ * @post The stream ISR vector is enabled and its priority configured.
+ * @post The stream must be freed using @p dmaStreamRelease() before it can
+ * be reused with another peripheral.
+ * @post The stream is in its post-reset state.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] priority IRQ priority mask for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return The operation status.
+ * @retval FALSE no error, stream taken.
+ * @retval TRUE error, stream already taken.
+ *
+ * @special
+ */
+bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param) {
+
+ chDbgCheck(dmastp != NULL, "dmaAllocate");
+
+ /* Checks if the stream is already taken.*/
+ if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0)
+ return TRUE;
+
+ /* Marks the stream as allocated.*/
+ dma_isr_redir[dmastp->selfindex].dma_func = func;
+ dma_isr_redir[dmastp->selfindex].dma_param = param;
+ dma_streams_mask |= (1 << dmastp->selfindex);
+
+ /* Enabling DMA clocks required by the current streams set.*/
+ if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0)
+ rccEnableDMA1(FALSE);
+
+ /* Putting the stream in a safe state.*/
+ dmaStreamDisable(dmastp);
+ dmaStreamClearInterrupt(dmastp);
+ dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE;
+
+ /* Enables the associated IRQ vector if a callback is defined.*/
+ if (func != NULL)
+ NVICEnableVector(dmastp->vector, CORTEX_PRIORITY_MASK(priority));
+
+ return FALSE;
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post The stream is again available.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+void dmaStreamRelease(const stm32_dma_stream_t *dmastp) {
+
+ chDbgCheck(dmastp != NULL, "dmaRelease");
+
+ /* Check if the streams is not taken.*/
+ chDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0,
+ "dmaRelease(), #1", "not allocated");
+
+ /* Disables the associated IRQ vector.*/
+ NVICDisableVector(dmastp->vector);
+
+ /* Marks the stream as not allocated.*/
+ dma_streams_mask &= ~(1 << dmastp->selfindex);
+
+ /* Shutting down clocks that are no more required, if any.*/
+ if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0)
+ rccDisableDMA1(FALSE);
+}
+
+#endif /* STM32_DMA_REQUIRED */
+
+/** @} */
diff --git a/os/hal/platforms/STM32L1xx/stm32_dma.h b/os/hal/platforms/STM32L1xx/stm32_dma.h
new file mode 100644
index 000000000..6afadfcc1
--- /dev/null
+++ b/os/hal/platforms/STM32L1xx/stm32_dma.h
@@ -0,0 +1,382 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file STM32L1xx/stm32_dma.h
+ * @brief DMA helper driver header.
+ * @note This file requires definitions from the ST header file stm32l1xx.h.
+ * @note This driver uses the new naming convention used for the STM32F2xx
+ * so the "DMA channels" are referred as "DMA streams".
+ *
+ * @addtogroup STM32L1xx_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 7
+
+/**
+ * @brief Mask of the ISR bits passed to the DMA callback functions.
+ */
+#define STM32_DMA_ISR_MASK 0x0F
+
+/**
+ * @brief Returns the channel associated to the specified stream.
+ *
+ * @param[in] n the stream number (0...STM32_DMA_STREAMS-1)
+ * @param[in] c a stream/channel association word, one channel per
+ * nibble, not associated channels must be set to 0xF
+ * @return Always zero, in this platform there is no dynamic
+ * association between streams and channels.
+ */
+#define STM32_DMA_GETCHANNEL(n, c) 0
+
+/**
+ * @name DMA streams identifiers
+ * @{
+ */
+/**
+ * @brief Returns an unique numeric identifier for a DMA stream.
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return An unique numeric stream identifier.
+ */
+#define STM32_DMA_STREAM_ID(dma, stream) ((stream) - 1)
+
+/**
+ * @brief Returns a DMA stream identifier mask.
+ *
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return A DMA stream identifier mask.
+ */
+#define STM32_DMA_STREAM_ID_MSK(dma, stream) \
+ (1 << STM32_DMA_STREAM_ID(dma, stream))
+
+/**
+ * @brief Checks if a DMA stream unique identifier belongs to a mask.
+ * @param[in] id the stream numeric identifier
+ * @param[in] mask the stream numeric identifiers mask
+ *
+ * @retval The check result.
+ * @retval FALSE id does not belong to the mask.
+ * @retval TRUE id belongs to the mask.
+ */
+#define STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask)))
+
+/**
+ * @brief Returns a pointer to a stm32_dma_stream_t structure.
+ *
+ * @param[in] id the stream numeric identifier
+ * @return A pointer to the stm32_dma_stream_t constant structure
+ * associated to the DMA stream.
+ */
+#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id])
+
+#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0)
+#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1)
+#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2)
+#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3)
+#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4)
+#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(5)
+#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(6)
+/** @} */
+
+/**
+ * @name CR register constants common to all DMA types
+ * @{
+ */
+#define STM32_DMA_CR_EN DMA_CCR1_EN
+#define STM32_DMA_CR_TEIE DMA_CCR1_TEIE
+#define STM32_DMA_CR_HTIE DMA_CCR1_HTIE
+#define STM32_DMA_CR_TCIE DMA_CCR1_TCIE
+#define STM32_DMA_CR_DIR_MASK (DMA_CCR1_DIR | DMA_CCR1_MEM2MEM)
+#define STM32_DMA_CR_DIR_P2M 0
+#define STM32_DMA_CR_DIR_M2P DMA_CCR1_DIR
+#define STM32_DMA_CR_DIR_M2M DMA_CCR1_MEM2MEM
+#define STM32_DMA_CR_CIRC DMA_CCR1_CIRC
+#define STM32_DMA_CR_PINC DMA_CCR1_PINC
+#define STM32_DMA_CR_MINC DMA_CCR1_MINC
+#define STM32_DMA_CR_PSIZE_MASK DMA_CCR1_PSIZE
+#define STM32_DMA_CR_PSIZE_BYTE 0
+#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR1_PSIZE_0
+#define STM32_DMA_CR_PSIZE_WORD DMA_CCR1_PSIZE_1
+#define STM32_DMA_CR_MSIZE_MASK DMA_CCR1_MSIZE
+#define STM32_DMA_CR_MSIZE_BYTE 0
+#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR1_MSIZE_0
+#define STM32_DMA_CR_MSIZE_WORD DMA_CCR1_MSIZE_1
+#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_MSIZE_MASK | \
+ STM32_DMA_CR_MSIZE_MASK)
+#define STM32_DMA_CR_PL_MASK DMA_CCR1_PL
+#define STM32_DMA_CR_PL(n) ((n) << 12)
+/** @} */
+
+/**
+ * @name CR register constants only found in enhanced DMA
+ * @{
+ */
+#define STM32_DMA_CR_DMEIE 0 /**< @brief Ignored by normal DMA. */
+#define STM32_DMA_CR_CHSEL_MASK 0 /**< @brief Ignored by normal DMA. */
+#define STM32_DMA_CR_CHSEL(n) 0 /**< @brief Ignored by normal DMA. */
+/** @} */
+
+/**
+ * @name Status flags passed to the ISR callbacks
+ * @{
+ */
+#define STM32_DMA_ISR_FEIF 0
+#define STM32_DMA_ISR_DMEIF 0
+#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1
+#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1
+#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA stream descriptor structure.
+ */
+typedef struct {
+ DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */
+ volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */
+ uint8_t ishift; /**< @brief Bits offset in xIFCR
+ register. */
+ uint8_t selfindex; /**< @brief Index to self in array. */
+ uint8_t vector; /**< @brief Associated IRQ vector. */
+} stm32_dma_stream_t;
+
+/**
+ * @brief STM32 DMA ISR function type.
+ *
+ * @param[in] p parameter for the registered function
+ * @param[in] flags pre-shifted content of the ISR register, the bits
+ * are aligned to bit zero
+ */
+typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Associates a peripheral data register to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the CPAR register
+ *
+ * @special
+ */
+#define dmaStreamSetPeripheral(dmastp, addr) { \
+ (dmastp)->channel->CPAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates a memory destination to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the CMAR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory0(dmastp, addr) { \
+ (dmastp)->channel->CMAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Sets the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] size value to be written in the CNDTR register
+ *
+ * @special
+ */
+#define dmaStreamSetTransactionSize(dmastp, size) { \
+ (dmastp)->channel->CNDTR = (uint32_t)(size); \
+}
+
+/**
+ * @brief Returns the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @return The number of transfers to be performed.
+ *
+ * @special
+ */
+#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR))
+
+/**
+ * @brief Programs the stream mode settings.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register
+ *
+ * @special
+ */
+#define dmaStreamSetMode(dmastp, mode) { \
+ (dmastp)->channel->CCR = (uint32_t)(mode); \
+}
+
+/**
+ * @brief DMA stream enable.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamEnable(dmastp) { \
+ (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \
+}
+
+/**
+ * @brief DMA stream disable.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamDisable(dmastp) { \
+ (dmastp)->channel->CCR &= ~STM32_DMA_CR_EN; \
+}
+
+/**
+ * @brief DMA stream interrupt sources clear.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamClearInterrupt(dmastp) { \
+ *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \
+}
+
+/**
+ * @brief Starts a memory to memory operation using the specified stream.
+ * @note The default transfer data mode is "byte to byte" but it can be
+ * changed by specifying extra options in the @p mode parameter.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register, this value
+ * is implicitly ORed with:
+ * - @p STM32_DMA_CR_MINC
+ * - @p STM32_DMA_CR_PINC
+ * - @p STM32_DMA_CR_DIR_M2M
+ * - @p STM32_DMA_CR_EN
+ * .
+ * @param[in] src source address
+ * @param[in] dst destination address
+ * @param[in] n number of data units to copy
+ */
+#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \
+ dmaStreamSetPeripheral(dmastp, src); \
+ dmaStreamSetMemory0(dmastp, dst); \
+ dmaStreamSetTransactionSize(dmastp, n); \
+ dmaStreamSetMode(dmastp, (mode) | \
+ STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \
+ STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \
+}
+
+/**
+ * @brief Polled wait for DMA transfer end.
+ * @pre The stream must have been allocated using @p dmaStreamAllocate().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ */
+#define dmaWaitCompletion(dmastp) \
+ while (((dmastp)->channel->CNDTR > 0) && \
+ ((dmastp)->channel->CCR & STM32_DMA_CR_EN))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dmaInit(void);
+ bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param);
+ void dmaStreamRelease(const stm32_dma_stream_t *dmastp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STM32_DMA_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/STM32L1xx/stm32_rcc.h b/os/hal/platforms/STM32L1xx/stm32_rcc.h
new file mode 100644
index 000000000..9ffcc07b4
--- /dev/null
+++ b/os/hal/platforms/STM32L1xx/stm32_rcc.h
@@ -0,0 +1,552 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file STM32L1xx/stm32_rcc.h
+ * @brief RCC helper driver header.
+ * @note This file requires definitions from the ST header file
+ * @p stm32l1xx.h.
+ *
+ * @addtogroup STM32L1xx_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 AHB bus.
+ *
+ * @param[in] mask AHB peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB(mask, lp) { \
+ RCC->AHBENR |= (mask); \
+ if (lp) \
+ RCC->AHBLPENR |= (mask); \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB bus.
+ *
+ * @param[in] mask AHB peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableAHB(mask, lp) { \
+ RCC->AHBENR &= ~(mask); \
+ if (lp) \
+ RCC->AHBLPENR &= ~(mask); \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB bus.
+ *
+ * @param[in] mask AHB peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB(mask) { \
+ RCC->AHBRSTR |= (mask); \
+ RCC->AHBRSTR = 0; \
+}
+/** @} */
+
+/**
+ * @brief 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 DMA peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA1(lp) rccEnableAHB(RCC_AHBENR_DMA1EN, lp)
+
+/**
+ * @brief Disables the DMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableDMA1(lp) rccDisableAHB(RCC_AHBENR_DMA1EN, lp)
+
+/**
+ * @brief Resets the DMA1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA1() rccResetAHB(RCC_AHBRSTR_DMA1RST)
+/** @} */
+
+/**
+ * @brief 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 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 TIM peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @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 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 USB peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USB peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSB(lp) rccEnableAPB1(RCC_APB1ENR_USBEN, lp)
+
+/**
+ * @brief Disables the USB peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccDisableUSB(lp) rccDisableAPB1(RCC_APB1ENR_USBEN, lp)
+
+/**
+ * @brief Resets the USB peripheral.
+ *
+ * @api
+ */
+#define rccResetUSB() rccResetAPB1(RCC_APB1RSTR_USBRST)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STM32_RCC_ */
+
+/** @} */
diff --git a/os/hal/platforms/STM32L1xx/stm32l1xx.h b/os/hal/platforms/STM32L1xx/stm32l1xx.h
index 48be82360..9c665d29b 100644
--- a/os/hal/platforms/STM32L1xx/stm32l1xx.h
+++ b/os/hal/platforms/STM32L1xx/stm32l1xx.h
@@ -191,6 +191,7 @@ typedef enum IRQn
*/
#include "core_cm3.h"
+/* CHIBIOS FIX */
/*#include "system_stm32l1xx.h"*/
#include <stdint.h>
@@ -411,6 +412,7 @@ typedef struct
/**
* @brief General Purpose IO
*/
+/* CHIBIOS FIX */
#if 0
typedef struct
{