From da9678f49a11241924c18902f7169c818a3cf995 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 22 Dec 2011 12:38:21 +0000 Subject: Provisional STM32F2xx support. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3649 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32F2xx/adc_lld.c | 416 +++++++++++++++ os/hal/platforms/STM32F2xx/adc_lld.h | 569 ++++++++++++++++++++ os/hal/platforms/STM32F2xx/hal_lld.c | 46 +- os/hal/platforms/STM32F2xx/hal_lld.h | 782 ++++++++++++++++++++-------- os/hal/platforms/STM32F2xx/platform.dox | 312 +++++++++++ os/hal/platforms/STM32F2xx/platform.mk | 18 +- os/hal/platforms/STM32F2xx/stm32_dma.c | 72 ++- os/hal/platforms/STM32F2xx/stm32_dma.h | 163 +++++- os/hal/platforms/STM32F2xx/stm32_rcc.h | 886 ++++++++++++++++++++++++++++++++ 9 files changed, 2969 insertions(+), 295 deletions(-) create mode 100644 os/hal/platforms/STM32F2xx/adc_lld.c create mode 100644 os/hal/platforms/STM32F2xx/adc_lld.h create mode 100644 os/hal/platforms/STM32F2xx/platform.dox create mode 100644 os/hal/platforms/STM32F2xx/stm32_rcc.h (limited to 'os/hal/platforms/STM32F2xx') diff --git a/os/hal/platforms/STM32F2xx/adc_lld.c b/os/hal/platforms/STM32F2xx/adc_lld.c new file mode 100644 index 000000000..b4c2f4d7e --- /dev/null +++ b/os/hal/platforms/STM32F2xx/adc_lld.c @@ -0,0 +1,416 @@ +/* + 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 . +*/ + +/** + * @file STM32F2xx/adc_lld.c + * @brief STM32F2xx ADC subsystem low level driver source. + * + * @addtogroup ADC + * @{ + */ + +#include "ch.h" +#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. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \ + defined(__DOXYGEN__) +/** + * @brief ADC interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(ADC1_2_3_IRQHandler) { + uint32_t sr; + + CH_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) { + + ADC->CCR = STM32_ADC_ADCPRE; + +#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 | + STM32_DMA_CR_EN; +#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 | + STM32_DMA_CR_EN; +#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 | + STM32_DMA_CR_EN; +#endif + + /* The shared vector is initialized on driver initialization and never + disabled.*/ + nvicEnableVector(ADC_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 */ + +#if STM32_ADC_USE_ADC2 + if (&ADCD2 == adcp) { + bool_t b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC2_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + chDbgAssert(!b, "adc_lld_start(), #2", "stream already allocated"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR); + rccEnableADC2(FALSE); + } +#endif /* STM32_ADC_USE_ADC2 */ + +#if STM32_ADC_USE_ADC3 + if (&ADCD3 == adcp) { + bool_t b; + b = dmaStreamAllocate(adcp->dmastp, + STM32_ADC_ADC3_DMA_IRQ_PRIORITY, + (stm32_dmaisr_t)adc_lld_serve_rx_interrupt, + (void *)adcp); + chDbgAssert(!b, "adc_lld_start(), #3", "stream already allocated"); + dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR); + rccEnableADC3(FALSE); + } +#endif /* STM32_ADC_USE_ADC3 */ + + /* 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 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->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; + 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; +} + +/** + * @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. + */ +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. + */ +void adcSTM32DisableVBATE(void) { + + ADC->CCR &= ~ADC_CCR_VBATE; +} + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/platforms/STM32F2xx/adc_lld.h b/os/hal/platforms/STM32F2xx/adc_lld.h new file mode 100644 index 000000000..9c5c7eee8 --- /dev/null +++ b/os/hal/platforms/STM32F2xx/adc_lld.h @@ -0,0 +1,569 @@ +/* + 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 . +*/ + +/** + * @file STM32F2xx/adc_lld.h + * @brief 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 Maximum HSE clock frequency. + */ +#define STM32_ADCCLK_MIN 600000 + +/** + * @brief Maximum HSE clock frequency. + * @note This value is arbitrary defined, the current datasheet does not + * define a maximum value (it is TBD). A value of 36MHz is mentioned + * but without relationship to VDD ranges. + */ +#define STM32_ADCCLK_MAX 42000000 +/** @} */ + +/** + * @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 STM32L15x datasheet + * for more info.
+ * See section 6.3.15 "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 TRUE +#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 TRUE +#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 TRUE +#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 + */ +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 + * 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 *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_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/platforms/STM32F2xx/hal_lld.c b/os/hal/platforms/STM32F2xx/hal_lld.c index 2d5d56895..2b3894bdd 100644 --- a/os/hal/platforms/STM32F2xx/hal_lld.c +++ b/os/hal/platforms/STM32F2xx/hal_lld.c @@ -19,8 +19,8 @@ */ /** - * @file STM32F2xx/hal_lld.c - * @brief STM32F2xx HAL subsystem low level driver source. + * @file STM32F4xx/hal_lld.c + * @brief STM32F4xx HAL subsystem low level driver source. * * @addtogroup HAL * @{ @@ -56,11 +56,13 @@ */ void hal_lld_init(void) { - /* Reset of all peripherals.*/ -// RCC->APB1RSTR = 0xFFFFFFFF; -// RCC->APB2RSTR = 0xFFFFFFFF; -// RCC->APB1RSTR = 0; -// RCC->APB2RSTR = 0; + /* 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); + rccResetAHB3(!0); + rccResetAPB1(!RCC_APB1RSTR_PWRRST); + rccResetAPB2(!0); /* SysTick initialization using the system clock.*/ SysTick->LOAD = STM32_HCLK / CH_FREQUENCY - 1; @@ -69,7 +71,10 @@ void hal_lld_init(void) { SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk; - +#if STM32_PVD_ENABLE + /* Programmable voltage detector initialization */ + PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK); +#endif /* STM32_PVD_ENABLE */ #if defined(STM32_DMA_REQUIRED) dmaInit(); @@ -83,16 +88,15 @@ void hal_lld_init(void) { * * @special */ -#if defined(STM32F2XX) || defined(__DOXYGEN__) -/** - * @brief Clocks and internal voltage initialization. - */ void stm32_clock_init(void) { #if !STM32_NO_INIT /* PWR clock enable.*/ RCC->APB1ENR = RCC_APB1ENR_PWREN; + /* PWR initialization.*/ + PWR->CR = 0; + /* Initial clocks setup and wait for HSI stabilization, the MSI clock is always enabled because it is the fallback clock when PLL the fails.*/ RCC->CR |= RCC_CR_HSION; @@ -134,7 +138,7 @@ void stm32_clock_init(void) { #if STM32_ACTIVATE_PLLI2S /* PLLI2S activation.*/ - RCC->PLLI2SCFGR = STM32_PLI2SR_VALUE | STM32_PLLI2SN_VALUE; + RCC->PLLI2SCFGR = STM32_PLLI2SR_VALUE | STM32_PLLI2SN_VALUE; RCC->CR |= RCC_CR_PLLI2SON; while (!(RCC->CR & RCC_CR_PLLI2SRDY)) ; /* Waits until PLLI2S is stable. */ @@ -144,19 +148,21 @@ void stm32_clock_init(void) { RCC->CFGR |= STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL | STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; - /* Flash setup. */ - FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | STM32_FLASHBITS; + /* Flash setup.*/ + FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | + STM32_FLASHBITS; - /* Switching to the configured clock source if it is different from MSI. */ + /* 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. */ + 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); } -#else -void stm32_clock_init(void) {} -#endif /** @} */ diff --git a/os/hal/platforms/STM32F2xx/hal_lld.h b/os/hal/platforms/STM32F2xx/hal_lld.h index 43a4a5c27..e9485df91 100644 --- a/os/hal/platforms/STM32F2xx/hal_lld.h +++ b/os/hal/platforms/STM32F2xx/hal_lld.h @@ -19,15 +19,16 @@ */ /** - * @file STM32F2xx/hal_lld.h - * @brief STM32F2xx HAL subsystem low level driver header. + * @file STM32F4xx/hal_lld.h + * @brief STM32F4xx 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_HSECLK. + * - STM32_VDD (as hundredths of Volt). * . * One of the following macros must also be defined: - * - STM32F2XX for High-performance STM32 F-2 devices. + * - STM32F4XX for High-performance STM32 F-4 devices. * . * * @addtogroup HAL @@ -37,27 +38,121 @@ #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 "stm32f2xx.h" -#define FALSE 0 -#define TRUE (!FALSE) +#include "stm32.h" /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ /** - * @brief Platform name. + * @name Platform identification + * @{ + */ +#define PLATFORM_NAME "STM32F2 High Performance" +/** @} */ + +/** + * @name Absolute Maximum Ratings + * @{ + */ +/** + * @brief Maximum system clock frequency. + */ +#define STM32_SYSCLK_MAX 120000000 + +/** + * @brief Maximum HSE clock frequency. + */ +#define STM32_HSECLK_MAX 26000000 + +/** + * @brief Minimum HSE clock frequency. + */ +#define STM32_HSECLK_MIN 1000000 + +/** + * @brief Maximum LSE clock frequency. + */ +#define STM32_LSECLK_MAX 1000000 + +/** + * @brief Minimum LSE clock frequency. + */ +#define STM32_LSECLK_MIN 32768 + +/** + * @brief Maximum PLLs input clock frequency. + */ +#define STM32_PLLIN_MAX 2000000 + +/** + * @brief Maximum 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 PLATFORM_NAME "STM32F2 High performance" +#define STM32_PLLOUT_MAX 120000000 +/** + * @brief Maximum PLL output clock frequency. + */ +#define STM32_PLLOUT_MIN 24000000 + +/** + * @brief Maximum APB1 clock frequency. + */ +#define STM32_PCLK1_MAX 30000000 + +/** + * @brief Maximum APB2 clock frequency. + */ +#define STM32_PCLK2_MAX 60000000 + +/** + * @brief Maximum SPI/I2S clock frequency. + */ +#define STM32_SPII2S_MAX 37500000 +/** @} */ + +/** + * @name Internal clock sources + * @{ + */ #define STM32_HSICLK 16000000 /**< High speed internal clock. */ -#define STM32_LSICLK 38000 /**< Low speed internal clock. */ +#define STM32_LSICLK 32000 /**< Low speed internal clock. */ +/** @} */ -/* RCC_PLLCFGR register bits definitions.*/ +/** + * @name PWR_CR register bits definitions + * @{ + */ +#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 0. */ +#define STM32_PLS_LEV2 (2 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV3 (3 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV4 (4 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV5 (5 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV6 (6 << 5) /**< PVD level 0. */ +#define STM32_PLS_LEV7 (7 << 5) /**< PVD level 0. */ +/** @} */ + +/** + * @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. */ @@ -66,8 +161,12 @@ #define STM32_PLLSRC_HSI (0 << 22) /**< PLL clock source is HSI. */ #define STM32_PLLSRC_HSE (1 << 22) /**< PLL clock source is HSE. */ +/** @} */ -/* RCC_CFGR register bits definitions.*/ +/** + * @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. */ @@ -106,6 +205,10 @@ #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 (1 << 24) /**< MCO1 divided by 2. */ @@ -120,33 +223,80 @@ #define STM32_MCO2PRE_DIV4 (6 << 27) /**< MCO2 divided by 4. */ #define STM32_MCO2PRE_DIV5 (7 << 27) /**< MCO2 divided by 5. */ -#define STM32_MCO2SEL_MASK (3 << 30) /**< MCO2 mask. */ -#define STM32_MCO2SEL_SYSCLK (0 << 30) /**< SYSCLK clock on MCO2 pin. */ -#define STM32_MCO2SEL_PLLI2S (1 << 30) /**< PLLI2S clock on MCO2 pin. */ -#define STM32_MCO2SEL_HSE (2 << 30) /**< HSE clock on MCO2 pin. */ -#define STM32_MCO2SEL_PLL (3 << 30) /**< PLL clock on MCO2 pin. */ +#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*/ -/* RCC_PLLI2SCFGR register bits definitions.*/ +/** + * @name RCC_PLLI2SCFGR register bits definitions + * @{ + */ #define STM32_PLLI2SN_MASK (511 << 6) /**< PLLI2SN mask. */ #define STM32_PLLI2SR_MASK (7 << 28) /**< PLLI2SR mask. */ +/** @} */ -/* STM32F2xx capabilities.*/ +/** + * @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. */ +/** @} */ + +/*===========================================================================*/ +/* 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 +/* CAN attributes.*/ #define STM32_HAS_CAN1 TRUE #define STM32_HAS_CAN2 TRUE +/* DAC attributes.*/ #define STM32_HAS_DAC TRUE +/* 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 @@ -159,42 +309,64 @@ /* 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 0x10000000 +#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 0x10000000 #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_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 +#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 -#define STM32_RTC_HAS_SUBSECONDS FALSE +#define STM32_RTC_HAS_SUBSECONDS TRUE +/* SDIO attributes.*/ #define STM32_HAS_SDIO TRUE +/* 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_HAS_SPI3 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 + +/* TIM attributes.*/ #define STM32_HAS_TIM1 TRUE #define STM32_HAS_TIM2 TRUE #define STM32_HAS_TIM3 TRUE #define STM32_HAS_TIM4 TRUE #define STM32_HAS_TIM5 TRUE -#define STM32_HAS_TIM6 FALSE -#define STM32_HAS_TIM7 FALSE +#define STM32_HAS_TIM6 TRUE +#define STM32_HAS_TIM7 TRUE #define STM32_HAS_TIM8 TRUE #define STM32_HAS_TIM9 TRUE #define STM32_HAS_TIM10 TRUE @@ -206,25 +378,67 @@ #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(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 0x00400400 +#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 0x00074040 + #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_HAS_USART6 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 +/** @} */ /*===========================================================================*/ /* 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_IRQHandler Vector48 /**< Tamper. */ -#define RTC_IRQHandler Vector4C /**< RTC. */ +#define TAMP_STAMP_IRQHandler Vector48 /**< Tamper and TimeStamp + through EXTI Line. */ +#define RTC_WKUP_IRQHandler Vector4C /**< RTC wakeup EXTI Line. */ #define FLASH_IRQHandler Vector50 /**< Flash. */ #define RCC_IRQHandler Vector54 /**< RCC. */ #define EXTI0_IRQHandler Vector58 /**< EXTI Line 0. */ @@ -263,8 +477,8 @@ #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 - line. */ +#define RTC_Alarm_IRQHandler VectorE4 /**< RTC alarms (A and B) + through EXTI line. */ #define OTG_FS_WKUP_IRQHandler VectorE8 /**< USB OTG FS Wakeup through EXTI line. */ #define TIM8_BRK_IRQHandler VectorEC /**< TIM8 Break. */ @@ -307,11 +521,17 @@ #define DCMI_IRQHandler Vector178 /**< DCMI. */ #define CRYP_IRQHandler Vector17C /**< CRYP. */ #define HASH_RNG_IRQHandler Vector180 /**< Hash and Rng. */ +#define FPU_IRQHandler Vector184 /**< Floating Point Unit. */ +/** @} */ /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @name Configuration options + * @{ + */ /** * @brief Disables the PWR/RCC initialization in the HAL. */ @@ -319,6 +539,20 @@ #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 or disables the HSI clock source. */ @@ -347,37 +581,30 @@ #define STM32_LSE_ENABLED FALSE #endif -/** - * @brief ADC clock setting. - */ -#if !defined(STM32_ADC_CLOCK_ENABLED) || defined(__DOXYGEN__) -#define STM32_ADC_CLOCK_ENABLED TRUE -#endif - /** * @brief USB clock setting. */ -#if !defined(STM32_USB_CLOCK_ENABLED) || defined(__DOXYGEN__) -#define STM32_USB_CLOCK_ENABLED TRUE +#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 32MHz system clock from - * the internal 16MHz HSI clock. + * @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 /** - * @brief Clock source for the PLL. + * @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 - * the external 25MHz HSE clock. + * an external 8MHz HSE clock. */ #if !defined(STM32_PLLSRC) || defined(__DOXYGEN__) #define STM32_PLLSRC STM32_PLLSRC_HSE @@ -387,46 +614,46 @@ * @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 25MHz HSE clock. + * an external 8MHz HSE clock. */ #if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLM_VALUE 25 +#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 25MHz HSE clock. + * an external 8MHz HSE clock. */ #if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLN_VALUE 240 +#define STM32_PLLN_VALUE 240 #endif /** - * @brief PLLP multiplier value. - * @note The allowed values are DIV2, DIV4, DIV6, DIV8. + * @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 25MHz HSE clock. + * an external 8MHz HSE clock. */ #if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLP_VALUE 2 +#define STM32_PLLP_VALUE 2 #endif /** * @brief PLLQ multiplier value. * @note The allowed values are 4..15. * @note The default value is calculated for a 120MHz system clock from - * an external 25MHz HSE clock. + * an external 8MHz HSE clock. */ #if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLQ_VALUE 5 +#define STM32_PLLQ_VALUE 5 #endif /** * @brief AHB prescaler value. * @note The default value is calculated for a 120MHz system clock from - * an external 25MHz HSE clock. + * an external 8MHz HSE clock. */ #if !defined(STM32_HPRE) || defined(__DOXYGEN__) #define STM32_HPRE STM32_HPRE_DIV1 @@ -447,10 +674,17 @@ #endif /** - * @brief RTC prescaler value. + * @brief RTC source clock. + */ +#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 25 +#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__) +#define STM32_RTCPRE_VALUE 8 #endif /** @@ -471,7 +705,7 @@ /** * @brief MC02 clock source value. - * @note The default value outputs SYSCLK / 5 on MC02 pin. + * @note The default value outputs SYSCLK / 4 on MC02 pin. */ #if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__) #define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK @@ -479,120 +713,226 @@ /** * @brief MC02 prescaler value. - * @note The default value outputs SYSCLK / 5 on MC02 pin. + * @note The default value outputs SYSCLK / 4 on MC02 pin. */ #if !defined(STM32_MCO2PRE) || defined(__DOXYGEN__) -#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_MCO2PRE STM32_MCO2PRE_DIV4 +#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. - * @note The default value is calculated for a 48000 I2S clock with - * I2SDIV = 12 and I2SODD = 1. */ #if !defined(STM32_PLLI2SN_VALUE) || defined(__DOXYGEN__) -#define STM32_PLLI2SN_VALUE 384 +#define STM32_PLLI2SN_VALUE 192 #endif /** * @brief PLLI2SR multiplier value. * @note The allowed values are 2..7. - * @note The default value is calculated for a 48000 I2S clock with - * I2SDIV = 12 and I2SODD = 1. */ -#if !defined(STM32_PLLI2SP_VALUE) || defined(__DOXYGEN__) -#define STM32_PLI2SLP_VALUE 5 +#if !defined(STM32_PLLI2SR_VALUE) || defined(__DOXYGEN__) +#define STM32_PLLI2SR_VALUE 5 #endif +/** @} */ /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ -/** - * @brief Maximum HSECLK. - */ -#define STM32_HSECLK_MAX 32000000 - -/** - * @brief Maximum SYSCLK. - */ -#define STM32_SYSCLK_MAX 120000000 - /** * @brief Maximum frequency thresholds and wait states for flash access. * @note The values are valid for 2.7V to 3.6V supply range. */ +#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 0 -#define STM32_4WS_THRESHOLD 0 -#define STM32_5WS_THRESHOLD 0 +#define STM32_3WS_THRESHOLD 120000000 +#define STM32_4WS_THRESHOLD 150000000 +#define STM32_5WS_THRESHOLD 168000000 #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 144000000 +#define STM32_6WS_THRESHOLD 168000000 +#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 138000000 +#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 128000000 +#else +#error "invalid VDD voltage specified" +#endif -/* HSI related checks.*/ +/* + * HSI related checks. + */ #if STM32_HSI_ENABLED #else /* !STM32_HSI_ENABLED */ -#if STM32_ADC_CLOCK_ENABLED || \ - (STM32_SW == STM32_SW_HSI) || \ - ((STM32_SW == STM32_SW_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSI)) || \ - (STM32_MCO1SEL == STM32_MCO1SEL_HSI) || \ + +#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 "required HSI clock is not enabled" +#error "HSI not enabled, required by STM32_MCO1SEL" +#endif + +#if (STM32_MCO2SEL == STM32_MCO2SEL_HSI) || \ + ((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.*/ +/* + * HSE related checks. + */ #if STM32_HSE_ENABLED + #if STM32_HSECLK == 0 -#error "impossible to activate HSE" -#endif -#if (STM32_HSECLK < 1000000) || (STM32_HSECLK > STM32_HSECLK_MAX) -#error "STM32_HSECLK outside acceptable range (1MHz...STM32_HSECLK_MAX)" +#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) || \ - ((STM32_SW == STM32_SW_PLL) && \ - (STM32_PLLSRC == STM32_PLLSRC_HSE)) || \ - (STM32_MCO1SEL == STM32_MCO1SEL_HSE) || \ + +#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)) || \ - (STM32_MCO2SEL == STM32_MCO2SEL_HSE) || \ + (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)) || \ - (STM_RTC_SOURCE == STM32_RTCSEL_HSEDIV) -#error "required HSE clock is not enabled" + (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.*/ +/* + * LSI related checks. + */ #if STM32_LSI_ENABLED #else /* !STM32_LSI_ENABLED */ -#if STM_RTCCLK == STM32_LSICLK + +#if STM32_RTCSEL == STM32_RTCSEL_LSI #error "required LSI clock is not enabled" #endif + #endif /* !STM32_LSI_ENABLED */ -/* LSE related checks.*/ +/* + * LSE related checks. + */ #if STM32_LSE_ENABLED + #if (STM32_LSECLK == 0) -#error "impossible to activate LSE" +#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 -#if (STM32_LSECLK < 1000) || (STM32_LSECLK > 1000000) -#error "STM32_LSECLK outside acceptable range (1...1000KHz)" + +#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 -#else /* !#if STM32_LSE_ENABLED */ -#if STM_RTCCLK == STM32_LSECLK -#error "required LSE clock is not enabled" + +/* + * 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 -#endif /* !#if STM32_LSE_ENABLED */ -/* PLL related checks.*/ -#if STM32_USB_CLOCK_ENABLED || \ +/* + * PLL enable check. + */ +#if STM32_CLOCK48_REQUIRED || \ (STM32_SW == STM32_SW_PLL) || \ (STM32_MCO1SEL == STM32_MCO1SEL_PLL) || \ (STM32_MCO2SEL == STM32_MCO2SEL_PLL) || \ @@ -605,16 +945,6 @@ #define STM32_ACTIVATE_PLL FALSE #endif -/** - * @brief STM32_PLLM field. - */ -#if ((STM32_PLLM_VALUE >= 2) && (STM32_PLLM_VALUE <= 63)) || \ - defined(__DOXYGEN__) -#define STM32_PLLM STM32_PLLM_VALUE -#else -#error "invalid STM32_PLLM_VALUE value specified" -#endif - /** * @brief STM32_PLLN field. */ @@ -643,39 +973,23 @@ /** * @brief STM32_PLLQ field. */ -#if ((STM32_PLLQ_VALUE >= 4) && (STM32_PLLQ_VALUE <= 15)) || \ +#if ((STM32_PLLQ_VALUE >= 4) && (STM32_PLLQ_VALUE <= 15)) || \ defined(__DOXYGEN__) #define STM32_PLLQ (STM32_PLLQ_VALUE << 24) #else #error "invalid STM32_PLLQ_VALUE value specified" #endif -/** - * @brief PLL input clock frequency. - */ -#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__) -#define STM32_PLLCLKIN STM32_HSECLK -#elif STM32_PLLSRC == STM32_PLLSRC_HSI -#define STM32_PLLCLKIN STM32_HSICLK -#else -#error "invalid STM32_PLLSRC value specified" -#endif - -/* PLL input frequency range check.*/ -#if (STM32_PLLCLKIN < 4000000) || (STM32_PLLCLKIN > 26000000) -#error "STM32_PLLCLKIN outside acceptable range (4...26MHz)" -#endif - /** * @brief PLL VCO frequency. */ -#define STM32_PLLVCO ((STM32_PLLCLKIN / STM32_PLLM_VALUE) * \ - STM32_PLLN_VALUE) +#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE) -/* PLL output frequency range check.*/ -#if (STM32_PLLVCO < 192000000) || (STM32_PLLVCO > 432000000) -#error STM32_PLLVCO -#error "STM32_PLLVCO outside acceptable range (192...432MHz)" +/* + * 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 /** @@ -683,16 +997,18 @@ */ #define STM32_PLLCLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE) -/* PLL output frequency range check.*/ -#if (STM32_PLLCLKOUT < 24000000) || (STM32_PLLCLKOUT > 120000000) -#error "STM32_PLLCLKOUT outside acceptable range (24...120MHz)" +/* + * 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 96000000 +#define STM32_SYSCLK STM32_HSICLK #elif (STM32_SW == STM32_SW_HSI) #define STM32_SYSCLK STM32_HSICLK #elif (STM32_SW == STM32_SW_HSE) @@ -733,7 +1049,9 @@ #error "invalid STM32_HPRE value specified" #endif -/* AHB frequency check.*/ +/* + * AHB frequency check. + */ #if STM32_HCLK > STM32_SYSCLK_MAX #error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)" #endif @@ -755,9 +1073,11 @@ #error "invalid STM32_PPRE1 value specified" #endif -/* APB1 frequency check.*/ -#if STM32_PCLK2 > STM32_SYSCLK_MAX -#error "STM32_PCLK1 exceeding maximum frequency (STM32_SYSCLK_MAX)" +/* + * APB1 frequency check. + */ +#if STM32_PCLK1 > STM32_PCLK1_MAX +#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)" #endif /** @@ -777,19 +1097,68 @@ #error "invalid STM32_PPRE2 value specified" #endif -/* APB2 frequency check.*/ -#if STM32_PCLK2 > STM32_SYSCLK_MAX -#error "STM32_PCLK2 exceeding maximum frequency (STM32_SYSCLK_MAX)" +/* + * 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 RTC frequency. + * @brief PLL activation flag. */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ +#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_RTCPRE (STM32_RTCPRE_VALUE << 16) +#define STM32_PLLI2SN (STM32_PLLI2SN_VALUE << 6) #else -#error "invalid STM32_RTCPRE value specified" +#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) + +/* + * PLLI2S output frequency range check. + */ +#if STM32_PLLI2SCLKOUT > STM32_SPII2S_MAX +#error "STM32_PLLI2SCLKOUT outside acceptable range (STM32_SPII2S_MAX)" #endif /** @@ -835,7 +1204,6 @@ #define STM_MCO2DIVCLK STM32_SYSCLK #elif STM32_MCO2SEL == STM32_MCO2SEL_PLLI2S #define STM_MCO2DIVCLK STM32_PLLI2S - #else #error "invalid STM32_MCO2SEL value specified" #endif @@ -860,9 +1228,19 @@ /** * @brief HSE divider toward RTC clock. */ -#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ +#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 HSE divider setting. + */ +#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 31)) || \ defined(__DOXYGEN__) -#define STM32_HSEDIVCLK (HSECLK / STM32_RTCPRE_VALUE) +#define STM32_RTCPRE (STM32_RTCPRE_VALUE << 16) #else #error "invalid STM32_RTCPRE value specified" #endif @@ -883,34 +1261,12 @@ #endif /** - * @brief ADC frequency. + * @brief 48MHz frequency. */ -#if (STM32_ADCPRE == STM32_ADCPRE_DIV2) || defined(__DOXYGEN__) -#define STM32_ADCCLK (STM32_PCLK2 / 2) -#elif STM32_ADCPRE == STM32_ADCPRE_DIV4 -#define STM32_ADCCLK (STM32_PCLK2 / 4) -#elif STM32_ADCPRE == STM32_ADCPRE_DIV6 -#define STM32_ADCCLK (STM32_PCLK2 / 6) -#elif STM32_ADCPRE == STM32_ADCPRE_DIV8 -#define STM32_ADCCLK (STM32_PCLK2 / 8) +#if STM32_CLOCK48_REQUIRED || defined(__DOXYGEN__) +#define STM32_PLL48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE) #else -#error "invalid STM32_ADCPRE value specified" -#endif - -/* ADC frequency check.*/ -#if STM32_ADCCLK > 30000000 -#error "STM32_ADCCLK exceeding maximum frequency (30MHz)" -#endif - -/** - * @brief OTG frequency. - */ -#if (STM32_OTGFSPRE == STM32_OTGFSPRE_DIV3) || defined(__DOXYGEN__) -#define STM32_OTGFSCLK (STM32_PLLVCO / 3) -#elif (STM32_OTGFSPRE == STM32_OTGFSPRE_DIV2) -#define STM32_OTGFSCLK (STM32_PLLVCO / 2) -#else -#error "invalid STM32_OTGFSPRE value specified" +#define STM32_PLL48CLK 0 #endif /** @@ -952,6 +1308,15 @@ #define STM32_FLASHBITS 0x00000007 #endif +/* There are differences in vector names in the various sub-families, + normalizing.*/ +#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 + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -964,8 +1329,9 @@ /* External declarations. */ /*===========================================================================*/ -/* STM32 DMA support code.*/ -//#include "stm32_dma.h" +/* STM32 DMA and RCC helpers.*/ +#include "stm32_dma.h" +#include "stm32_rcc.h" #ifdef __cplusplus extern "C" { diff --git a/os/hal/platforms/STM32F2xx/platform.dox b/os/hal/platforms/STM32F2xx/platform.dox new file mode 100644 index 000000000..8a8d85c63 --- /dev/null +++ b/os/hal/platforms/STM32F2xx/platform.dox @@ -0,0 +1,312 @@ +/* + 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 . +*/ + +/** + * @defgroup STM32F2xx_DRIVERS STM32F2xx Drivers + * @details This section describes all the supported drivers on the STM32F2xx + * platform and the implementation details of the single drivers. + * + * @ingroup platforms + */ + +/** + * @defgroup STM32F2xx_HAL STM32F2xx Initialization Support + * @details The STM32F2xx HAL support is responsible for system initialization. + * + * @section stm32f2xx_hal_1 Supported HW resources + * - PLL1. + * - PLL2. + * - RCC. + * - Flash. + * . + * @section stm32f2xx_hal_2 STM32F2xx HAL driver implementation features + * - PLL startup and stabilization. + * - Clock tree initialization. + * - Clock source selection. + * - Flash wait states initialization based on the selected clock options. + * - SYSTICK initialization based on current clock and kernel required rate. + * - DMA support initialization. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_ADC STM32F2xx ADC Support + * @details The STM32F2xx ADC driver supports the ADC peripherals using DMA + * channels for maximum performance. + * + * @section stm32f2xx_adc_1 Supported HW resources + * - ADC1. + * - ADC2. + * - ADC3. + * - DMA2. + * . + * @section stm32f2xx_adc_2 STM32F2xx 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 STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_EXT STM32F2xx EXT Support + * @details The STM32F2xx EXT driver uses the EXTI peripheral. + * + * @section stm32f2xx_ext_1 Supported HW resources + * - EXTI. + * . + * @section stm32f2xx_ext_2 STM32F2xx 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 STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_GPT STM32F2xx GPT Support + * @details The STM32F2xx GPT driver uses the TIMx peripherals. + * + * @section stm32f2xx_gpt_1 Supported HW resources + * - TIM1. + * - TIM2. + * - TIM3. + * - TIM4. + * - TIM5. + * - TIM8. + * . + * @section stm32f2xx_gpt_2 STM32F2xx GPT driver implementation features + * - Each timer can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable TIMx interrupts priority level. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_ICU STM32F2xx ICU Support + * @details The STM32F2xx ICU driver uses the TIMx peripherals. + * + * @section stm32f2xx_icu_1 Supported HW resources + * - TIM1. + * - TIM2. + * - TIM3. + * - TIM4. + * - TIM5. + * - TIM8. + * . + * @section stm32f2xx_icu_2 STM32F2xx ICU driver implementation features + * - Each timer can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable TIMx interrupts priority level. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_PAL STM32F2xx PAL Support + * @details The STM32F2xx PAL driver uses the GPIO peripherals. + * + * @section stm32f2xx_pal_1 Supported HW resources + * - GPIOA. + * - GPIOB. + * - GPIOC. + * - GPIOD. + * - GPIOE. + * - GPIOF. + * - GPIOG. + * - GPIOH. + * - GPIOI. + * . + * @section stm32f2xx_pal_2 STM32F2xx PAL driver implementation features + * The PAL driver implementation fully supports the following hardware + * capabilities: + * - 16 bits wide ports. + * - Atomic set/reset functions. + * - Atomic set+reset function (atomic bus operations). + * - Output latched regardless of the pad setting. + * - Direct read of input pads regardless of the pad setting. + * . + * @section stm32f2xx_pal_3 Supported PAL setup modes + * The STM32F2xx PAL driver supports the following I/O modes: + * - @p PAL_MODE_RESET. + * - @p PAL_MODE_UNCONNECTED. + * - @p PAL_MODE_INPUT. + * - @p PAL_MODE_INPUT_PULLUP. + * - @p PAL_MODE_INPUT_PULLDOWN. + * - @p PAL_MODE_INPUT_ANALOG. + * - @p PAL_MODE_OUTPUT_PUSHPULL. + * - @p PAL_MODE_OUTPUT_OPENDRAIN. + * - @p PAL_MODE_ALTERNATE (non standard). + * . + * Any attempt to setup an invalid mode is ignored. + * + * @section stm32f2xx_pal_4 Suboptimal behavior + * The STM32F2xx GPIO is less than optimal in several areas, the limitations + * should be taken in account while using the PAL driver: + * - Pad/port toggling operations are not atomic. + * - Pad/group mode setup is not atomic. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_PWM STM32F2xx PWM Support + * @details The STM32F2xx PWM driver uses the TIMx peripherals. + * + * @section stm32f2xx_pwm_1 Supported HW resources + * - TIM1. + * - TIM2. + * - TIM3. + * - TIM4. + * - TIM5. + * - TIM8. + * . + * @section stm32f2xx_pwm_2 STM32F2xx PWM driver implementation features + * - Each timer can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Four independent PWM channels per timer. + * - Programmable TIMx interrupts priority level. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_SERIAL STM32F2xx Serial Support + * @details The STM32F2xx Serial driver uses the USART/UART peripherals in a + * buffered, interrupt driven, implementation. + * + * @section stm32f2xx_serial_1 Supported HW resources + * The serial driver can support any of the following hardware resources: + * - USART1. + * - USART2. + * - USART3. + * - UART4. + * - UART5. + * - USART6. + * . + * @section stm32f2xx_serial_2 STM32F2xx Serial driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Each UART/USART can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Fully interrupt driven. + * - Programmable priority levels for each UART/USART. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_SPI STM32F2xx SPI Support + * @details The SPI driver supports the STM32F2xx SPI peripherals using DMA + * channels for maximum performance. + * + * @section stm32f2xx_spi_1 Supported HW resources + * - SPI1. + * - SPI2. + * - SPI3. + * - DMA1. + * - DMA2. + * . + * @section stm32f2xx_spi_2 STM32F2xx SPI driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Each SPI can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable interrupt priority levels for each SPI. + * - DMA is used for receiving and transmitting. + * - Programmable DMA bus priority for each DMA channel. + * - Programmable DMA interrupt priority for each DMA channel. + * - Programmable DMA error hook. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_UART STM32F2xx UART Support + * @details The UART driver supports the STM32F2xx USART peripherals using DMA + * channels for maximum performance. + * + * @section stm32f2xx_uart_1 Supported HW resources + * The UART driver can support any of the following hardware resources: + * - USART1. + * - USART2. + * - USART3. + * - DMA1. + * - DMA2. + * . + * @section stm32f2xx_uart_2 STM32F2xx UART driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Each UART/USART can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable interrupt priority levels for each UART/USART. + * - DMA is used for receiving and transmitting. + * - Programmable DMA bus priority for each DMA channel. + * - Programmable DMA interrupt priority for each DMA channel. + * - Programmable DMA error hook. + * . + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_PLATFORM_DRIVERS STM32F2xx Platform Drivers + * @details Platform support drivers. Platform drivers do not implement HAL + * standard driver templates, their role is to support platform + * specific functionalities. + * + * @ingroup STM32F2xx_DRIVERS + */ + +/** + * @defgroup STM32F2xx_DMA STM32F2xx 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 stm32f2xx_dma_1 Supported HW resources + * The DMA driver can support any of the following hardware resources: + * - DMA1. + * - DMA2. + * . + * @section stm32f2xx_dma_2 STM32F2xx 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 STM32F2xx_PLATFORM_DRIVERS + */ + +/** + * @defgroup STM32F2xx_RCC STM32F2xx 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 stm32f2xx_rcc_2 STM32F2xx RCC driver implementation features + * - Peripherals reset. + * - Peripherals clock enable. + * - Periplerals clock disable. + * . + * @ingroup STM32F2xx_PLATFORM_DRIVERS + */ diff --git a/os/hal/platforms/STM32F2xx/platform.mk b/os/hal/platforms/STM32F2xx/platform.mk index 64365e897..8ddebf729 100644 --- a/os/hal/platforms/STM32F2xx/platform.mk +++ b/os/hal/platforms/STM32F2xx/platform.mk @@ -1,12 +1,22 @@ -# List of all the STM32L1xx platform files. -PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F2xx/hal_lld.c \ +# List of all the STM32F2xx platform files. +PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F2xx/stm32_dma.c \ + ${CHIBIOS}/os/hal/platforms/STM32F2xx/hal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32F2xx/adc_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/spi_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/i2c_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2/rtc_lld.c \ # Required include directories PLATFORMINC = ${CHIBIOS}/os/hal/platforms/STM32F2xx \ ${CHIBIOS}/os/hal/platforms/STM32 \ - ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 + ${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \ + ${CHIBIOS}/os/hal/platforms/STM32/RTCv2 \ + + diff --git a/os/hal/platforms/STM32F2xx/stm32_dma.c b/os/hal/platforms/STM32F2xx/stm32_dma.c index 95b3e555c..04d8ecbe9 100644 --- a/os/hal/platforms/STM32F2xx/stm32_dma.c +++ b/os/hal/platforms/STM32F2xx/stm32_dma.c @@ -19,10 +19,10 @@ */ /** - * @file DMAv2/stm32_dma.c + * @file STM32F2xx/stm32_dma.c * @brief Enhanced DMA helper driver code. * - * @addtogroup STM32_DMA + * @addtogroup STM32F2xx_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 @@ -76,22 +76,22 @@ * instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc. */ const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { - {0, DMA1, DMA1_Stream0, &DMA1->LIFCR, 0}, - {1, DMA1, DMA1_Stream1, &DMA1->LIFCR, 6}, - {2, DMA1, DMA1_Stream2, &DMA1->LIFCR, 16}, - {3, DMA1, DMA1_Stream3, &DMA1->LIFCR, 22}, - {4, DMA1, DMA1_Stream4, &DMA1->HIFCR, 0}, - {5, DMA1, DMA1_Stream5, &DMA1->HIFCR, 6}, - {6, DMA1, DMA1_Stream6, &DMA1->HIFCR, 16}, - {7, DMA1, DMA1_Stream7, &DMA1->HIFCR, 22}, - {8, DMA2, DMA2_Stream0, &DMA2->LIFCR, 0}, - {9, DMA2, DMA2_Stream1, &DMA2->LIFCR, 6}, - {10, DMA2, DMA2_Stream2, &DMA2->LIFCR, 16}, - {11, DMA2, DMA2_Stream3, &DMA2->LIFCR, 22}, - {12, DMA2, DMA2_Stream4, &DMA2->HIFCR, 0}, - {13, DMA2, DMA2_Stream5, &DMA2->HIFCR, 6}, - {14, DMA2, DMA2_Stream6, &DMA2->HIFCR, 16}, - {15, DMA2, DMA2_Stream7, &DMA2->HIFCR, 22}, + {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}, }; /*===========================================================================*/ @@ -102,8 +102,8 @@ const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = { * @brief DMA ISR redirector type. */ typedef struct { - stm32_dmaisr_t dma_func; - void *dma_param; + stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */ + void *dma_param; /**< @brief DMA callback parameter. */ } dma_isr_redir_t; /** @@ -467,7 +467,7 @@ bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, chDbgCheck(dmastp != NULL, "dmaAllocate"); /* Checks if the stream is already taken.*/ - if ((dma_streams_mask & dmastp->mask) != 0) + if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0) return TRUE; /* Marks the stream as allocated.*/ @@ -476,20 +476,16 @@ bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp, dma_streams_mask |= (1 << dmastp->selfindex); /* Enabling DMA clocks required by the current streams set.*/ - if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) { - RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; - RCC->AHB1LPENR |= RCC_AHB1LPENR_DMA1LPEN; - } - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) { - RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; - RCC->AHB1LPENR |= RCC_AHB1LPENR_DMA2LPEN; - } + 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); dmaStreamClearInterrupt(dmastp); - dmastp->channel->CR = STM32_DMA_CR_RESET_VALUE; - dmastp->channel->FCR = STM32_DMA_FCR_RESET_VALUE; + 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) @@ -516,7 +512,7 @@ void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { chDbgCheck(dmastp != NULL, "dmaRelease"); /* Check if the streams is not taken.*/ - chDbgAssert((dma_streams_mask & dmastp->mask) != 0, + chDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0, "dmaRelease(), #1", "not allocated"); /* Disables the associated IRQ vector.*/ @@ -526,14 +522,10 @@ void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { 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) { - RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA1EN; - RCC->AHB1LPENR &= ~RCC_AHB1LPENR_DMA1LPEN; - } - if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) { - RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA2EN; - RCC->AHB1LPENR &= ~RCC_AHB1LPENR_DMA2LPEN; - } + 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/platforms/STM32F2xx/stm32_dma.h b/os/hal/platforms/STM32F2xx/stm32_dma.h index af18497fc..d57cae4be 100644 --- a/os/hal/platforms/STM32F2xx/stm32_dma.h +++ b/os/hal/platforms/STM32F2xx/stm32_dma.h @@ -19,12 +19,12 @@ */ /** - * @file DMAv2/stm32_dma.h + * @file STM32F2xx/stm32_dma.h * @brief Enhanced-DMA helper driver header. * @note This file requires definitions from the ST STM32F2xx header file * stm32f2xx.h. * - * @addtogroup STM32_DMA + * @addtogroup STM32F2xx_DMA * @{ */ @@ -46,30 +46,81 @@ */ #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)) + +/** + * @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 * @{ */ -#define STM32_DMA1_STREAM0 (&_stm32_dma_streams[0]) -#define STM32_DMA1_STREAM1 (&_stm32_dma_streams[1]) -#define STM32_DMA1_STREAM2 (&_stm32_dma_streams[2]) -#define STM32_DMA1_STREAM3 (&_stm32_dma_streams[3]) -#define STM32_DMA1_STREAM4 (&_stm32_dma_streams[4]) -#define STM32_DMA1_STREAM5 (&_stm32_dma_streams[5]) -#define STM32_DMA1_STREAM6 (&_stm32_dma_streams[6]) -#define STM32_DMA1_STREAM7 (&_stm32_dma_streams[7]) -#define STM32_DMA2_STREAM0 (&_stm32_dma_streams[8]) -#define STM32_DMA2_STREAM1 (&_stm32_dma_streams[9]) -#define STM32_DMA2_STREAM2 (&_stm32_dma_streams[10]) -#define STM32_DMA2_STREAM3 (&_stm32_dma_streams[11]) -#define STM32_DMA2_STREAM4 (&_stm32_dma_streams[12]) -#define STM32_DMA2_STREAM5 (&_stm32_dma_streams[13]) -#define STM32_DMA2_STREAM6 (&_stm32_dma_streams[14]) -#define STM32_DMA2_STREAM7 (&_stm32_dma_streams[15]) +/** + * @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 @@ -90,12 +141,15 @@ #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_MSIZE_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 + * @name CR register constants only found in STM32F2xx/STM32F2xx + * @{ */ #define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE #define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL @@ -117,7 +171,8 @@ /** @} */ /** - * @name FCR register constants only found in STM32F2xx + * @name FCR register constants only found in STM32F2xx/STM32F2xx + * @{ */ #define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE #define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS @@ -155,7 +210,7 @@ * @brief STM32 DMA stream descriptor structure. */ typedef struct { - DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */ + 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. */ @@ -176,9 +231,15 @@ 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 @@ -192,6 +253,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); /** * @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 @@ -218,6 +281,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); /** * @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 @@ -231,6 +296,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); /** * @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. @@ -242,6 +309,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); /** * @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 @@ -255,6 +324,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); /** * @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 @@ -268,18 +339,22 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); /** * @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] dmachp pointer to a stm32_dma_stream_t structure + * @param[in] dmastp pointer to a stm32_dma_stream_t structure * * @special */ -#define dmaStreamEnable(dmachp) { \ +#define dmaStreamEnable(dmastp) { \ (dmastp)->stream->CR |= 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 * @@ -292,6 +367,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); /** * @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 * @@ -301,6 +378,46 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags); *(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->CNDTR > 0) && \ + ((dmastp)->stream->CCR & STM32_DMA_CR_EN)) +/** @} */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ diff --git a/os/hal/platforms/STM32F2xx/stm32_rcc.h b/os/hal/platforms/STM32F2xx/stm32_rcc.h new file mode 100644 index 000000000..19ad4484d --- /dev/null +++ b/os/hal/platforms/STM32F2xx/stm32_rcc.h @@ -0,0 +1,886 @@ +/* + 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 . +*/ + +/** + * @file STM32F2xx/stm32_rcc.h + * @brief RCC helper driver header. + * @note This file requires definitions from the ST header file + * @p stm32f2xx.h. + * + * @addtogroup STM32F2xx_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; \ +} +/** @} */ + +/** + * @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 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) +/** @} */ + +/** + * @brief 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) +/** @} */ + +/** + * @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 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) +/** @} */ + +/** + * @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 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 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 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 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) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _STM32_RCC_ */ + +/** @} */ -- cgit v1.2.3